8210777: Update Graal

Reviewed-by: kvn
This commit is contained in:
Dean Long 2018-11-15 09:04:07 -08:00
parent c8ebf4da3b
commit 971575362a
307 changed files with 11871 additions and 2737 deletions

View File

@ -450,21 +450,17 @@ jdk.internal.vm.compiler_ADD_JAVAC_FLAGS += -parameters -XDstringConcat=inline \
jdk.internal.vm.compiler_EXCLUDES += \
jdk.internal.vm.compiler.collections.test \
org.graalvm.compiler.processor \
org.graalvm.compiler.core.match.processor \
org.graalvm.compiler.nodeinfo.processor \
org.graalvm.compiler.options.processor \
org.graalvm.compiler.serviceprovider.processor \
org.graalvm.compiler.replacements.processor \
org.graalvm.compiler.replacements.jdk9.test \
jdk.tools.jaotc.test \
org.graalvm.compiler.api.directives.test \
org.graalvm.compiler.api.test \
org.graalvm.compiler.asm.aarch64.test \
org.graalvm.compiler.asm.amd64.test \
org.graalvm.compiler.asm.sparc.test \
org.graalvm.compiler.asm.test \
org.graalvm.compiler.core.aarch64.test \
org.graalvm.compiler.core.amd64.test \
org.graalvm.compiler.core.sparc.test \
org.graalvm.compiler.core.jdk9.test \
org.graalvm.compiler.core.match.processor \
org.graalvm.compiler.core.test \
org.graalvm.compiler.debug.test \
org.graalvm.compiler.graph.test \
@ -477,10 +473,18 @@ jdk.internal.vm.compiler_EXCLUDES += \
org.graalvm.compiler.lir.test \
org.graalvm.compiler.loop.test \
org.graalvm.compiler.microbenchmarks \
org.graalvm.compiler.nodeinfo.processor \
org.graalvm.compiler.nodes.test \
org.graalvm.compiler.options.processor \
org.graalvm.compiler.options.test \
org.graalvm.compiler.phases.common.test \
org.graalvm.compiler.processor \
org.graalvm.compiler.replacements.jdk12.test \
org.graalvm.compiler.replacements.jdk9.test \
org.graalvm.compiler.replacements.jdk9_11.test \
org.graalvm.compiler.replacements.processor \
org.graalvm.compiler.replacements.test \
org.graalvm.compiler.serviceprovider.processor \
org.graalvm.compiler.test \
org.graalvm.compiler.virtual.bench \
org.graalvm.micro.benchmarks \

View File

@ -59,6 +59,7 @@ ifeq ($(INCLUDE_GRAAL), true)
-Xlint:none \
-processorpath $(BUILDTOOLS_OUTPUTDIR)/jdk.vm.compiler.replacements.verifier.jar \
--add-exports jdk.unsupported/sun.misc=ALL-UNNAMED \
--add-exports java.base/jdk.internal.misc=ALL-UNNAMED \
### Copy 3rd party libs
$(eval $(call SetupCopyFiles, COPY_GRAALUNIT_LIBS, \
@ -81,6 +82,7 @@ ifeq ($(INCLUDE_GRAAL), true)
$(SRC_DIR)/org.graalvm.compiler.asm.test/src \
$(SRC_DIR)/org.graalvm.compiler.core.amd64.test/src \
$(SRC_DIR)/org.graalvm.compiler.core.test/src \
$(SRC_DIR)/org.graalvm.compiler.core.jdk9.test/src \
$(SRC_DIR)/org.graalvm.compiler.debug.test/src \
$(SRC_DIR)/org.graalvm.compiler.graph.test/src \
$(SRC_DIR)/org.graalvm.compiler.hotspot.amd64.test/src \
@ -92,6 +94,9 @@ ifeq ($(INCLUDE_GRAAL), true)
$(SRC_DIR)/org.graalvm.compiler.nodes.test/src \
$(SRC_DIR)/org.graalvm.compiler.options.test/src \
$(SRC_DIR)/org.graalvm.compiler.phases.common.test/src \
$(SRC_DIR)/org.graalvm.compiler.replacements.jdk12.test/src \
$(SRC_DIR)/org.graalvm.compiler.replacements.jdk9.test/src \
$(SRC_DIR)/org.graalvm.compiler.replacements.jdk9_11.test/src \
$(SRC_DIR)/org.graalvm.compiler.replacements.test/src \
$(SRC_DIR)/org.graalvm.compiler.test/src \
$(SRC_DIR)/org.graalvm.util.test/src \

View File

@ -33,8 +33,8 @@ import org.graalvm.compiler.core.common.CompilationIdentifier;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.hotspot.HotSpotBackend;
import org.graalvm.compiler.hotspot.HotSpotCompiledCodeBuilder;
import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
import org.graalvm.compiler.hotspot.meta.HotSpotInvokeDynamicPlugin;
import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
import org.graalvm.compiler.java.GraphBuilderPhase;
import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory;
import org.graalvm.compiler.lir.phases.LIRSuites;
@ -167,7 +167,7 @@ final class AOTBackend {
void printCompiledMethod(HotSpotResolvedJavaMethod resolvedMethod, CompilationResult compResult) {
// This is really not installing the method.
InstalledCode installedCode = codeCache.addCode(resolvedMethod, HotSpotCompiledCodeBuilder.createCompiledCode(codeCache, resolvedMethod, null, compResult), null, null);
InstalledCode installedCode = codeCache.addCode(resolvedMethod, HotSpotCompiledCodeBuilder.createCompiledCode(codeCache, resolvedMethod, null, compResult, graalOptions), null, null);
String disassembly = codeCache.disassemble(installedCode);
if (disassembly != null) {
main.printer.printlnDebug(disassembly);

View File

@ -32,8 +32,8 @@ import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
import org.graalvm.compiler.code.CompilationResult;
import org.graalvm.compiler.core.GraalCompilerOptions;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.debug.TTY;
import org.graalvm.compiler.debug.DebugContext.Activation;
import org.graalvm.compiler.debug.TTY;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.printer.GraalDebugHandlersFactory;
import org.graalvm.compiler.serviceprovider.GraalServices;
@ -143,7 +143,7 @@ final class AOTCompilationTask implements Runnable, Comparable<Object> {
aotBackend.printCompiledMethod((HotSpotResolvedJavaMethod) method, compResult);
}
result = new CompiledMethodInfo(compResult, new AOTHotSpotResolvedJavaMethod((HotSpotResolvedJavaMethod) method, aotBackend.getBackend()));
result = new CompiledMethodInfo(compResult, new AOTHotSpotResolvedJavaMethod((HotSpotResolvedJavaMethod) method, aotBackend.getBackend(), graalOptions));
}
private String getMethodDescription() {

View File

@ -28,6 +28,8 @@ package jdk.tools.jaotc;
import org.graalvm.compiler.code.CompilationResult;
import org.graalvm.compiler.core.target.Backend;
import org.graalvm.compiler.hotspot.HotSpotCompiledCodeBuilder;
import org.graalvm.compiler.options.OptionValues;
import jdk.vm.ci.hotspot.HotSpotCompiledCode;
import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
@ -35,10 +37,12 @@ final class AOTHotSpotResolvedJavaMethod implements JavaMethodInfo {
private final HotSpotResolvedJavaMethod method;
private final Backend backend;
private final OptionValues options;
AOTHotSpotResolvedJavaMethod(HotSpotResolvedJavaMethod method, Backend backend) {
AOTHotSpotResolvedJavaMethod(HotSpotResolvedJavaMethod method, Backend backend, OptionValues options) {
this.method = method;
this.backend = backend;
this.options = options;
}
@Override
@ -54,7 +58,7 @@ final class AOTHotSpotResolvedJavaMethod implements JavaMethodInfo {
@Override
public HotSpotCompiledCode compiledCode(CompilationResult result) {
return HotSpotCompiledCodeBuilder.createCompiledCode(backend.getCodeCache(), method, null, result);
return HotSpotCompiledCodeBuilder.createCompiledCode(backend.getCodeCache(), method, null, result, options);
}
}

View File

@ -29,6 +29,7 @@ import org.graalvm.compiler.code.CompilationResult;
import org.graalvm.compiler.core.target.Backend;
import org.graalvm.compiler.hotspot.HotSpotCompiledCodeBuilder;
import org.graalvm.compiler.hotspot.stubs.Stub;
import org.graalvm.compiler.options.OptionValues;
import jdk.vm.ci.hotspot.HotSpotCompiledCode;
@ -36,10 +37,12 @@ final class AOTStub implements JavaMethodInfo {
private final Stub stub;
private final Backend backend;
private OptionValues options;
AOTStub(Stub stub, Backend backend) {
AOTStub(Stub stub, Backend backend, OptionValues options) {
this.stub = stub;
this.backend = backend;
this.options = options;
}
@Override
@ -54,7 +57,7 @@ final class AOTStub implements JavaMethodInfo {
@Override
public HotSpotCompiledCode compiledCode(CompilationResult result) {
return HotSpotCompiledCodeBuilder.createCompiledCode(backend.getCodeCache(), null, null, result);
return HotSpotCompiledCodeBuilder.createCompiledCode(backend.getCodeCache(), null, null, result, options);
}
}

View File

@ -30,16 +30,15 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map.Entry;
import jdk.tools.jaotc.binformat.BinaryContainer;
import jdk.tools.jaotc.binformat.ByteContainer;
import jdk.tools.jaotc.binformat.HeaderContainer;
import org.graalvm.compiler.code.CompilationResult;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.hotspot.HotSpotHostBackend;
import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProvider;
import org.graalvm.compiler.hotspot.stubs.Stub;
import jdk.tools.jaotc.binformat.BinaryContainer;
import jdk.tools.jaotc.binformat.ByteContainer;
import jdk.tools.jaotc.binformat.HeaderContainer;
import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
import jdk.vm.ci.hotspot.HotSpotVMConfigStore;
import jdk.vm.ci.hotspot.VMField;
@ -190,7 +189,7 @@ final class DataBuilder {
for (Stub stub : foreignCallsProvider.getStubs()) {
try (DebugContext.Scope scope = debug.scope("CompileStubs")) {
CompilationResult result = stub.getCompilationResult(debug, backend);
CompiledMethodInfo cm = new CompiledMethodInfo(result, new AOTStub(stub, backend));
CompiledMethodInfo cm = new CompiledMethodInfo(result, new AOTStub(stub, backend, debug.getOptions()));
stubs.add(cm);
} catch (Throwable e) {
throw debug.handle(e);

View File

@ -150,10 +150,16 @@ public final class HotSpotGraalManagement implements HotSpotGraalManagementRegis
*/
synchronized void poll() {
if (platformMBeanServer == null) {
ArrayList<MBeanServer> servers = MBeanServerFactory.findMBeanServer(null);
if (!servers.isEmpty()) {
platformMBeanServer = ManagementFactory.getPlatformMBeanServer();
process();
try {
ArrayList<MBeanServer> servers = MBeanServerFactory.findMBeanServer(null);
if (!servers.isEmpty()) {
platformMBeanServer = ManagementFactory.getPlatformMBeanServer();
process();
}
} catch (SecurityException e) {
// Without permission to find or create the MBeanServer,
// we cannot process any Graal mbeans.
deferred = null;
}
} else {
process();

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2018, 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
@ -22,6 +22,22 @@
*/
package jdk.internal.vm.compiler.collections.test;
import java.util.Arrays;
@ -117,7 +133,7 @@ public class EconomicMapImplTest {
Assert.assertTrue(set.add(newInteger(0)));
}
@SuppressWarnings("deprecation")
@SuppressWarnings({"deprecation", "unused"})
private static Integer newInteger(int value) {
return new Integer(value);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2018, 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
@ -22,6 +22,22 @@
*/
package jdk.internal.vm.compiler.collections.test;
import java.util.Arrays;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2018, 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
@ -22,6 +22,22 @@
*/
package jdk.internal.vm.compiler.collections.test;
import java.util.LinkedHashMap;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2018, 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
@ -22,6 +22,22 @@
*/
package jdk.internal.vm.compiler.collections.test;
import java.util.ArrayList;
@ -145,7 +161,7 @@ public class EconomicSetTest {
Assert.assertEquals(newInteger(9), finalList.get(0));
}
@SuppressWarnings("deprecation")
@SuppressWarnings({"deprecation", "unused"})
private static Integer newInteger(int value) {
return new Integer(value);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2018, 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
@ -22,6 +22,22 @@
*/
package jdk.internal.vm.compiler.collections.test;
import jdk.internal.vm.compiler.collections.Equivalence;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2018, 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
@ -22,6 +22,22 @@
*/
package jdk.internal.vm.compiler.collections.test;
import jdk.internal.vm.compiler.collections.Pair;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2018, 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
@ -22,6 +22,22 @@
*/
package jdk.internal.vm.compiler.collections;
import java.util.Iterator;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2018, 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
@ -22,6 +22,22 @@
*/
package jdk.internal.vm.compiler.collections;
import java.util.Iterator;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2018, 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
@ -22,6 +22,22 @@
*/
package jdk.internal.vm.compiler.collections;
import java.util.Iterator;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2018, 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
@ -22,6 +22,22 @@
*/
package jdk.internal.vm.compiler.collections;
/**

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2018, 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
@ -22,6 +22,22 @@
*/
package jdk.internal.vm.compiler.collections;
/**

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2018, 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
@ -22,6 +22,22 @@
*/
package jdk.internal.vm.compiler.collections;
import java.util.Objects;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2018, 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
@ -22,6 +22,22 @@
*/
package jdk.internal.vm.compiler.collections;
/**

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2018, 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
@ -22,6 +22,22 @@
*/
package jdk.internal.vm.compiler.collections;
/**

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2018, 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
@ -22,6 +22,22 @@
*/
package jdk.internal.vm.compiler.collections;
/**

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2018, 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
@ -35,4 +35,20 @@
*/
package jdk.internal.vm.compiler.collections;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2018, 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
@ -22,6 +22,22 @@
*/
package jdk.internal.vm.compiler.word;
/**

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2018, 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
@ -22,6 +22,22 @@
*/
package jdk.internal.vm.compiler.word;
// JaCoCo Exclude

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2018, 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
@ -22,6 +22,22 @@
*/
package jdk.internal.vm.compiler.word;
/**
@ -959,7 +975,8 @@ public interface Pointer extends UnsignedWord, PointerBase {
void writeObject(WordBase offset, Object val);
/**
* Atomically exchanges memory at address {@code (this + offset)}. Both the base address and
* In a single atomic step, compares the memory at address {@code (this + offset)} to the
* expected value, and if equal, exchanges it for the new value. Both the base address and
* offset are in bytes.
* <p>
* The offset is always treated as a {@link SignedWord} value. However, the static type is
@ -967,17 +984,19 @@ public interface Pointer extends UnsignedWord, PointerBase {
* knows that the highest-order bit of the unsigned value is never used).
*
* @param offset the signed offset for the memory access
* @param expectedValue the expected value of the atomic exchange
* @param newValue the new value of the atomic exchange
* @param expectedValue the expected current value at the memory address
* @param newValue the new value for the atomic exchange
* @param locationIdentity the identity of the memory location
* @return The value after the atomic exchange
* @return The value that was read for comparison, which is {@code expectedValue} if the
* exchange was performed.
*
* @since 1.0
*/
int compareAndSwapInt(WordBase offset, int expectedValue, int newValue, LocationIdentity locationIdentity);
/**
* Atomically exchanges memory at address {@code (this + offset)}. Both the base address and
* In a single atomic step, compares the memory at address {@code (this + offset)} to the
* expected value, and if equal, exchanges it for the new value. Both the base address and
* offset are in bytes.
* <p>
* The offset is always treated as a {@link SignedWord} value. However, the static type is
@ -985,17 +1004,19 @@ public interface Pointer extends UnsignedWord, PointerBase {
* knows that the highest-order bit of the unsigned value is never used).
*
* @param offset the signed offset for the memory access
* @param expectedValue the expected value of the atomic exchange
* @param newValue the new value of the atomic exchange
* @param expectedValue the expected current value at the memory address
* @param newValue the new value for the atomic exchange
* @param locationIdentity the identity of the memory location
* @return The value after the atomic exchange
* @return The value that was read for comparison, which is {@code expectedValue} if the
* exchange was performed.
*
* @since 1.0
*/
long compareAndSwapLong(WordBase offset, long expectedValue, long newValue, LocationIdentity locationIdentity);
/**
* Atomically exchanges memory at address {@code (this + offset)}. Both the base address and
* In a single atomic step, compares the memory at address {@code (this + offset)} to the
* expected value, and if equal, exchanges it for the new value. Both the base address and
* offset are in bytes.
* <p>
* The offset is always treated as a {@link SignedWord} value. However, the static type is
@ -1003,17 +1024,19 @@ public interface Pointer extends UnsignedWord, PointerBase {
* knows that the highest-order bit of the unsigned value is never used).
*
* @param offset the signed offset for the memory access
* @param expectedValue the expected value of the atomic exchange
* @param newValue the new value of the atomic exchange
* @param expectedValue the expected current value at the memory address
* @param newValue the new value for the atomic exchange
* @param locationIdentity the identity of the memory location
* @return The value after the atomic exchange
* @return The value that was read for comparison, which is {@code expectedValue} if the
* exchange was performed.
*
* @since 1.0
*/
<T extends WordBase> T compareAndSwapWord(WordBase offset, T expectedValue, T newValue, LocationIdentity locationIdentity);
/**
* Atomically exchanges memory at address {@code (this + offset)}. Both the base address and
* In a single atomic step, compares the memory at address {@code (this + offset)} to the
* expected value, and if equal, exchanges it for the new value. Both the base address and
* offset are in bytes.
* <p>
* The offset is always treated as a {@link SignedWord} value. However, the static type is
@ -1021,17 +1044,19 @@ public interface Pointer extends UnsignedWord, PointerBase {
* knows that the highest-order bit of the unsigned value is never used).
*
* @param offset the signed offset for the memory access
* @param expectedValue the expected value of the atomic exchange
* @param newValue the new value of the atomic exchange
* @param expectedValue the expected current value at the memory address
* @param newValue the new value for the atomic exchange
* @param locationIdentity the identity of the memory location
* @return The value after the atomic exchange
* @return The value that was read for comparison, which is {@code expectedValue} if the
* exchange was performed.
*
* @since 1.0
*/
Object compareAndSwapObject(WordBase offset, Object expectedValue, Object newValue, LocationIdentity locationIdentity);
/**
* Atomically exchanges memory at address {@code (this + offset)}. Both the base address and
* In a single atomic step, compares the memory at address {@code (this + offset)} to the
* expected value, and if equal, exchanges it for the new value. Both the base address and
* offset are in bytes.
* <p>
* The offset is always treated as a {@link SignedWord} value. However, the static type is
@ -1039,8 +1064,8 @@ public interface Pointer extends UnsignedWord, PointerBase {
* knows that the highest-order bit of the unsigned value is never used).
*
* @param offset the signed offset for the memory access
* @param expectedValue the expected value of the atomic exchange
* @param newValue the new value of the atomic exchange
* @param expectedValue the expected current value at the memory address
* @param newValue the new value for the atomic exchange
* @param locationIdentity the identity of the memory location
* @return {@code true} if successful. False return indicates that the actual value was not
* equal to the expected value.
@ -1050,7 +1075,8 @@ public interface Pointer extends UnsignedWord, PointerBase {
boolean logicCompareAndSwapInt(WordBase offset, int expectedValue, int newValue, LocationIdentity locationIdentity);
/**
* Atomically exchanges memory at address {@code (this + offset)}. Both the base address and
* In a single atomic step, compares the memory at address {@code (this + offset)} to the
* expected value, and if equal, exchanges it for the new value. Both the base address and
* offset are in bytes.
* <p>
* The offset is always treated as a {@link SignedWord} value. However, the static type is
@ -1058,8 +1084,8 @@ public interface Pointer extends UnsignedWord, PointerBase {
* knows that the highest-order bit of the unsigned value is never used).
*
* @param offset the signed offset for the memory access
* @param expectedValue the expected value of the atomic exchange
* @param newValue the new value of the atomic exchange
* @param expectedValue the expected current value at the memory address
* @param newValue the new value for the atomic exchange
* @param locationIdentity the identity of the memory location
* @return {@code true} if successful. False return indicates that the actual value was not
* equal to the expected value.
@ -1069,7 +1095,8 @@ public interface Pointer extends UnsignedWord, PointerBase {
boolean logicCompareAndSwapLong(WordBase offset, long expectedValue, long newValue, LocationIdentity locationIdentity);
/**
* Atomically exchanges memory at address {@code (this + offset)}. Both the base address and
* In a single atomic step, compares the memory at address {@code (this + offset)} to the
* expected value, and if equal, exchanges it for the new value. Both the base address and
* offset are in bytes.
* <p>
* The offset is always treated as a {@link SignedWord} value. However, the static type is
@ -1077,8 +1104,8 @@ public interface Pointer extends UnsignedWord, PointerBase {
* knows that the highest-order bit of the unsigned value is never used).
*
* @param offset the signed offset for the memory access
* @param expectedValue the expected value of the atomic exchange
* @param newValue the new value of the atomic exchange
* @param expectedValue the expected current value at the memory address
* @param newValue the new value for the atomic exchange
* @param locationIdentity the identity of the memory location
* @return {@code true} if successful. False return indicates that the actual value was not
* equal to the expected value.
@ -1088,7 +1115,8 @@ public interface Pointer extends UnsignedWord, PointerBase {
boolean logicCompareAndSwapWord(WordBase offset, WordBase expectedValue, WordBase newValue, LocationIdentity locationIdentity);
/**
* Atomically exchanges memory at address {@code (this + offset)}. Both the base address and
* In a single atomic step, compares the memory at address {@code (this + offset)} to the
* expected value, and if equal, exchanges it for the new value. Both the base address and
* offset are in bytes.
* <p>
* The offset is always treated as a {@link SignedWord} value. However, the static type is
@ -1096,8 +1124,8 @@ public interface Pointer extends UnsignedWord, PointerBase {
* knows that the highest-order bit of the unsigned value is never used).
*
* @param offset the signed offset for the memory access
* @param expectedValue the expected value of the atomic exchange
* @param newValue the new value of the atomic exchange
* @param expectedValue the expected current value at the memory address
* @param newValue the new value for the atomic exchange
* @param locationIdentity the identity of the memory location
* @return {@code true} if successful. False return indicates that the actual value was not
* equal to the expected value.
@ -1206,68 +1234,77 @@ public interface Pointer extends UnsignedWord, PointerBase {
void writeObject(int offset, Object val);
/**
* Atomically exchanges memory at address {@code (this + offset)}. Both the base address and
* In a single atomic step, compares the memory at address {@code (this + offset)} to the
* expected value, and if equal, exchanges it for the new value. Both the base address and
* offset are in bytes.
*
* @param offset the signed offset for the memory access
* @param expectedValue the expected value of the atomic exchange
* @param newValue the new value of the atomic exchange
* @param expectedValue the expected current value at the memory address
* @param newValue the new value for the atomic exchange
* @param locationIdentity the identity of the memory location
* @return The value after the atomic exchange
* @return The value that was read for comparison, which is {@code expectedValue} if the
* exchange was performed.
*
* @since 1.0
*/
int compareAndSwapInt(int offset, int expectedValue, int newValue, LocationIdentity locationIdentity);
/**
* Atomically exchanges memory at address {@code (this + offset)}. Both the base address and
* In a single atomic step, compares the memory at address {@code (this + offset)} to the
* expected value, and if equal, exchanges it for the new value. Both the base address and
* offset are in bytes.
*
* @param offset the signed offset for the memory access
* @param expectedValue the expected value of the atomic exchange
* @param newValue the new value of the atomic exchange
* @param expectedValue the expected current value at the memory address
* @param newValue the new value for the atomic exchange
* @param locationIdentity the identity of the memory location
* @return The value after the atomic exchange
* @return The value that was read for comparison, which is {@code expectedValue} if the
* exchange was performed.
*
* @since 1.0
*/
long compareAndSwapLong(int offset, long expectedValue, long newValue, LocationIdentity locationIdentity);
/**
* Atomically exchanges memory at address {@code (this + offset)}. Both the base address and
* In a single atomic step, compares the memory at address {@code (this + offset)} to the
* expected value, and if equal, exchanges it for the new value. Both the base address and
* offset are in bytes.
*
* @param offset the signed offset for the memory access
* @param expectedValue the expected value of the atomic exchange
* @param newValue the new value of the atomic exchange
* @param expectedValue the expected current value at the memory address
* @param newValue the new value for the atomic exchange
* @param locationIdentity the identity of the memory location
* @return The value after the atomic exchange
* @return The value that was read for comparison, which is {@code expectedValue} if the
* exchange was performed.
*
* @since 1.0
*/
<T extends WordBase> T compareAndSwapWord(int offset, T expectedValue, T newValue, LocationIdentity locationIdentity);
/**
* Atomically exchanges memory at address {@code (this + offset)}. Both the base address and
* In a single atomic step, compares the memory at address {@code (this + offset)} to the
* expected value, and if equal, exchanges it for the new value. Both the base address and
* offset are in bytes.
*
* @param offset the signed offset for the memory access
* @param expectedValue the expected value of the atomic exchange
* @param newValue the new value of the atomic exchange
* @param expectedValue the expected current value at the memory address
* @param newValue the new value for the atomic exchange
* @param locationIdentity the identity of the memory location
* @return The value after the atomic exchange
* @return The value that was read for comparison, which is {@code expectedValue} if the
* exchange was performed.
*
* @since 1.0
*/
Object compareAndSwapObject(int offset, Object expectedValue, Object newValue, LocationIdentity locationIdentity);
/**
* Atomically exchanges memory at address {@code (this + offset)}. Both the base address and
* In a single atomic step, compares the memory at address {@code (this + offset)} to the
* expected value, and if equal, exchanges it for the new value. Both the base address and
* offset are in bytes.
*
* @param offset the signed offset for the memory access
* @param expectedValue the expected value of the atomic exchange
* @param newValue the new value of the atomic exchange
* @param expectedValue the expected current value at the memory address
* @param newValue the new value for the atomic exchange
* @param locationIdentity the identity of the memory location
* @return {@code true} if successful. False return indicates that the actual value was not
* equal to the expected value.
@ -1277,12 +1314,13 @@ public interface Pointer extends UnsignedWord, PointerBase {
boolean logicCompareAndSwapInt(int offset, int expectedValue, int newValue, LocationIdentity locationIdentity);
/**
* Atomically exchanges memory at address {@code (this + offset)}. Both the base address and
* In a single atomic step, compares the memory at address {@code (this + offset)} to the
* expected value, and if equal, exchanges it for the new value. Both the base address and
* offset are in bytes.
*
* @param offset the signed offset for the memory access
* @param expectedValue the expected value of the atomic exchange
* @param newValue the new value of the atomic exchange
* @param expectedValue the expected current value at the memory address
* @param newValue the new value for the atomic exchange
* @param locationIdentity the identity of the memory location
* @return {@code true} if successful. False return indicates that the actual value was not
* equal to the expected value.
@ -1292,12 +1330,13 @@ public interface Pointer extends UnsignedWord, PointerBase {
boolean logicCompareAndSwapLong(int offset, long expectedValue, long newValue, LocationIdentity locationIdentity);
/**
* Atomically exchanges memory at address {@code (this + offset)}. Both the base address and
* In a single atomic step, compares the memory at address {@code (this + offset)} to the
* expected value, and if equal, exchanges it for the new value. Both the base address and
* offset are in bytes.
*
* @param offset the signed offset for the memory access
* @param expectedValue the expected value of the atomic exchange
* @param newValue the new value of the atomic exchange
* @param expectedValue the expected current value at the memory address
* @param newValue the new value for the atomic exchange
* @param locationIdentity the identity of the memory location
* @return {@code true} if successful. False return indicates that the actual value was not
* equal to the expected value.
@ -1307,12 +1346,13 @@ public interface Pointer extends UnsignedWord, PointerBase {
boolean logicCompareAndSwapWord(int offset, WordBase expectedValue, WordBase newValue, LocationIdentity locationIdentity);
/**
* Atomically exchanges memory at address {@code (this + offset)}. Both the base address and
* In a single atomic step, compares the memory at address {@code (this + offset)} to the
* expected value, and if equal, exchanges it for the new value. Both the base address and
* offset are in bytes.
*
* @param offset the signed offset for the memory access
* @param expectedValue the expected value of the atomic exchange
* @param newValue the new value of the atomic exchange
* @param expectedValue the expected current value at the memory address
* @param newValue the new value for the atomic exchange
* @param locationIdentity the identity of the memory location
* @return {@code true} if successful. False return indicates that the actual value was not
* equal to the expected value.

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2018, 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
@ -22,6 +22,22 @@
*/
package jdk.internal.vm.compiler.word;
/**

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2018, 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
@ -22,6 +22,22 @@
*/
package jdk.internal.vm.compiler.word;
/**

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2018, 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
@ -22,6 +22,22 @@
*/
package jdk.internal.vm.compiler.word;
/**

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2018, 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
@ -22,6 +22,22 @@
*/
package jdk.internal.vm.compiler.word;
/**

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2018, 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
@ -22,6 +22,22 @@
*/
package jdk.internal.vm.compiler.word;
import jdk.internal.vm.compiler.word.impl.WordBoxFactory;

View File

@ -22,6 +22,22 @@
*/
package jdk.internal.vm.compiler.word.impl;
import jdk.internal.vm.compiler.word.WordBase;

View File

@ -22,6 +22,22 @@
*/
package jdk.internal.vm.compiler.word.impl;
import java.lang.annotation.ElementType;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 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
@ -33,4 +33,20 @@
*/
package jdk.internal.vm.compiler.word;

View File

@ -2775,7 +2775,8 @@ public abstract class AArch64Assembler extends Assembler {
WFE(0x2),
WFI(0x3),
SEV(0x4),
SEVL(0x5);
SEVL(0x5),
CSDB(0x14);
private final int encoding;

View File

@ -1475,6 +1475,14 @@ public class AArch64MacroAssembler extends AArch64Assembler {
super.hint(SystemHint.NOP);
}
/**
* Consumption of Speculative Data Barrier. This is a memory barrier that controls speculative
* execution and data value prediction.
*/
public void csdb() {
super.hint(SystemHint.CSDB);
}
/**
* Same as {@link #nop()}.
*/

View File

@ -59,6 +59,7 @@ import jdk.vm.ci.amd64.AMD64;
import jdk.vm.ci.amd64.AMD64.CPUFeature;
import jdk.vm.ci.amd64.AMD64Kind;
import jdk.vm.ci.code.Register;
import jdk.vm.ci.code.Register.RegisterCategory;
import jdk.vm.ci.code.TargetDescription;
import jdk.vm.ci.meta.PlatformKind;
@ -269,8 +270,12 @@ public abstract class AMD64BaseAssembler extends Assembler {
return ((AMD64) target.arch).getFeatures().contains(feature);
}
protected static boolean inRC(RegisterCategory rc, Register r) {
return r.getRegisterCategory().equals(rc);
}
protected static int encode(Register r) {
assert r.encoding >= 0 && (r.getRegisterCategory().equals(XMM) ? r.encoding < 32 : r.encoding < 16) : "encoding out of range: " + r.encoding;
assert r.encoding >= 0 && (inRC(XMM, r) ? r.encoding < 32 : r.encoding < 16) : "encoding out of range: " + r.encoding;
return r.encoding & 0x7;
}
@ -296,6 +301,10 @@ public abstract class AMD64BaseAssembler extends Assembler {
private static final int REXWRB = 0x4D;
private static final int REXWRX = 0x4E;
private static final int REXWRXB = 0x4F;
private static final int VEX2 = 0xC5;
private static final int VEX3 = 0xC4;
private static final int EVEX = 0x62;
}
protected final void rexw() {
@ -797,12 +806,17 @@ public abstract class AMD64BaseAssembler extends Assembler {
@Override
public void simdPrefix(Register reg, Register nds, AMD64Address rm, int sizePrefix, int opcodeEscapePrefix, boolean isRexW) {
emitVEX(L128, sizePrefixToPP(sizePrefix), opcodeEscapePrefixToMMMMM(opcodeEscapePrefix), isRexW ? W1 : W0, getRXB(reg, rm), nds.isValid() ? nds.encoding : 0);
assert reg.encoding < 16 : "encoding out of range: " + reg.encoding;
assert nds.encoding < 16 : "encoding out of range: " + nds.encoding;
emitVEX(L128, sizePrefixToPP(sizePrefix), opcodeEscapePrefixToMMMMM(opcodeEscapePrefix), isRexW ? W1 : W0, getRXB(reg, rm), nds.isValid() ? nds.encoding : 0, true);
}
@Override
public void simdPrefix(Register dst, Register nds, Register src, int sizePrefix, int opcodeEscapePrefix, boolean isRexW) {
emitVEX(L128, sizePrefixToPP(sizePrefix), opcodeEscapePrefixToMMMMM(opcodeEscapePrefix), isRexW ? W1 : W0, getRXB(dst, src), nds.isValid() ? nds.encoding : 0);
assert dst.encoding < 16 : "encoding out of range: " + dst.encoding;
assert src.encoding < 16 : "encoding out of range: " + src.encoding;
assert nds.encoding < 16 : "encoding out of range: " + nds.encoding;
emitVEX(L128, sizePrefixToPP(sizePrefix), opcodeEscapePrefixToMMMMM(opcodeEscapePrefix), isRexW ? W1 : W0, getRXB(dst, src), nds.isValid() ? nds.encoding : 0, true);
}
}
@ -822,6 +836,46 @@ public abstract class AMD64BaseAssembler extends Assembler {
simdEncoder.simdPrefix(dst, nds, src, size.sizePrefix, opcodeEscapePrefix, isRexW);
}
// @formatter:off
//
// Instruction Format and VEX illustrated below (optional []):
//
// #of bytes: 2,3 1 1 1 1,2,4 1
// [Prefixes] VEX OpCode ModR/M [SIB] [Disp8*N] [Immediate]
// [Disp16,32]
//
// VEX: 0xC4 | P1 | P2
//
// 7 6 5 4 3 2 1 0
// P1 R X B m m m m m P[ 7:0]
// P2 W v v v v L p p P[15:8]
//
// VEX: 0xC5 | B1
//
// 7 6 5 4 3 2 1 0
// P1 R v v v v L p p P[7:0]
//
// Figure. Bit Field Layout of the VEX Prefix
//
// Table. VEX Prefix Bit Field Functional Grouping
//
// Notation Bit field Group Position Comment
// ---------- ------------------------- -------- -------------------
// VEX.RXB Next-8 register specifier P[7:5] Combine with ModR/M.reg, ModR/M.rm (base, index/vidx).
// VEX.R REX.R inverse P[7] Combine with EVEX.R and ModR/M.reg.
// VEX.X REX.X inverse P[6] Combine with EVEX.B and ModR/M.rm, when SIB/VSIB absent.
// VEX.B REX.B inverse P[5]
// VEX.mmmmmm 0F, 0F_38, 0F_3A encoding P[4:0] b01/0x0F, b10/0F_38, b11/0F_3A (all other reserved)
//
// VEX.W Opcode specific P[15]
// VEX.vvvv A register specifier P[14:11] In inverse form, b1111 if not used.
// P[6:3]
// VEX.L Vector length/RC P[10] b0/scalar or 128b vec, b1/256b vec.
// P[2]
// VEX.pp Compressed legacy prefix P[9:8] b00/None, b01/0x66, b10/0xF3, b11/0xF2
// P[1:0]
// @formatter:on
/**
* Low-level function to encode and emit the VEX prefix.
* <p>
@ -846,8 +900,8 @@ public abstract class AMD64BaseAssembler extends Assembler {
* This function automatically chooses the 2 or 3 byte encoding, based on the XBW flags and the
* m-mmmm field.
*/
protected final void emitVEX(int l, int pp, int mmmmm, int w, int rxb, int vvvv) {
assert ((AMD64) target.arch).getFeatures().contains(CPUFeature.AVX) : "emitting VEX prefix on a CPU without AVX support";
protected final void emitVEX(int l, int pp, int mmmmm, int w, int rxb, int vvvv, boolean checkAVX) {
assert !checkAVX || ((AMD64) target.arch).getFeatures().contains(CPUFeature.AVX) : "emitting VEX prefix on a CPU without AVX support";
assert l == L128 || l == L256 : "invalid value for VEX.L";
assert pp == P_ || pp == P_66 || pp == P_F3 || pp == P_F2 : "invalid value for VEX.pp";
@ -867,7 +921,7 @@ public abstract class AMD64BaseAssembler extends Assembler {
byte2 |= l << 2;
byte2 |= pp;
emitByte(0xC5);
emitByte(Prefix.VEX2);
emitByte(byte2);
} else {
// 3 byte encoding
@ -881,7 +935,7 @@ public abstract class AMD64BaseAssembler extends Assembler {
byte3 |= l << 2;
byte3 |= pp;
emitByte(0xC4);
emitByte(Prefix.VEX3);
emitByte(byte2);
emitByte(byte3);
}
@ -900,12 +954,12 @@ public abstract class AMD64BaseAssembler extends Assembler {
}
}
public final void vexPrefix(Register dst, Register nds, Register src, AVXSize size, int pp, int mmmmm, int w) {
emitVEX(getLFlag(size), pp, mmmmm, w, getRXB(dst, src), nds.isValid() ? nds.encoding() : 0);
public final void vexPrefix(Register dst, Register nds, Register src, AVXSize size, int pp, int mmmmm, int w, boolean checkAVX) {
emitVEX(getLFlag(size), pp, mmmmm, w, getRXB(dst, src), nds.isValid() ? nds.encoding() : 0, checkAVX);
}
public final void vexPrefix(Register dst, Register nds, AMD64Address src, AVXSize size, int pp, int mmmmm, int w) {
emitVEX(getLFlag(size), pp, mmmmm, w, getRXB(dst, src), nds.isValid() ? nds.encoding() : 0);
public final void vexPrefix(Register dst, Register nds, AMD64Address src, AVXSize size, int pp, int mmmmm, int w, boolean checkAVX) {
emitVEX(getLFlag(size), pp, mmmmm, w, getRXB(dst, src), nds.isValid() ? nds.encoding() : 0, checkAVX);
}
protected static final class EVEXPrefixConfig {
@ -986,6 +1040,51 @@ public abstract class AMD64BaseAssembler extends Assembler {
}
}
// @formatter:off
//
// Instruction Format and EVEX illustrated below (optional []):
//
// #of bytes: 4 1 1 1 1,2,4 1
// [Prefixes] EVEX OpCode ModR/M [SIB] [Disp8*N] [Immediate]
// [Disp16,32]
//
// The EVEX prefix is a 4-byte prefix, with the first two bytes derived from unused encoding
// form of the 32-bit-mode-only BOUND instruction. The layout of the EVEX prefix is shown in
// the figure below. The first byte must be 0x62, followed by three pay-load bytes, denoted
// as P1, P2, and P3 individually or collectively as P[23:0] (see below).
//
// EVEX: 0x62 | P1 | P2 | P3
//
// 7 6 5 4 3 2 1 0
// P1 R X B R' 0 0 m m P[ 7: 0]
// P2 W v v v v 1 p p P[15: 8]
// P3 z L' L b V' a a a P[23:16]
//
// Figure. Bit Field Layout of the EVEX Prefix
//
// Table. EVEX Prefix Bit Field Functional Grouping
//
// Notation Bit field Group Position Comment
// --------- -------------------------- -------- -----------------------
// EVEX.RXB Next-8 register specifier P[7:5] Combine with ModR/M.reg, ModR/M.rm (base, index/vidx).
// EVEX.X High-16 register specifier P[6] Combine with EVEX.B and ModR/M.rm, when SIB/VSIB absent.
// EVEX.R' High-16 register specifier P[4] Combine with EVEX.R and ModR/M.reg.
// -- Reserved P[3:2] Must be 0.
// EVEX.mm Compressed legacy escape P[1:0] Identical to low two bits of VEX.mmmmm.
//
// EVEX.W Osize promotion/Opcode ext P[15]
// EVEX.vvvv NDS register specifier P[14:11] Same as VEX.vvvv.
// -- Fixed Value P[10] Must be 1.
// EVEX.pp Compressed legacy prefix P[9:8] Identical to VEX.pp.
//
// EVEX.z Zeroing/Merging P[23]
// EVEX.L'L Vector length/RC P[22:21]
// EVEX.b Broadcast/RC/SAE Context P[20]
// EVEX.V' High-16 NDS/VIDX register P[19] Combine with EVEX.vvvv or VSIB when present.
// EVEX.aaa Embedded opmask register P[18:16]
//
// @formatter:on
/**
* Low-level function to encode and emit the EVEX prefix.
* <p>
@ -1021,13 +1120,13 @@ public abstract class AMD64BaseAssembler extends Assembler {
assert (rxb & 0x07) == rxb : "invalid value for EVEX.RXB";
assert (reg & 0x1F) == reg : "invalid value for EVEX.R'";
assert (vvvvv & 0x1F) == vvvvv : "invalid value for EVEX.vvvvv";
assert (vvvvv & 0x1F) == vvvvv : "invalid value for EVEX.V'vvvv";
assert z == Z0 || z == Z1 : "invalid value for EVEX.z";
assert b == B0 || b == B1 : "invalid value for EVEX.b";
assert (aaa & 0x07) == aaa : "invalid value for EVEX.aaa";
emitByte(0x62);
emitByte(Prefix.EVEX);
int p1 = 0;
p1 |= ((rxb ^ 0x07) & 0x07) << 5;
p1 |= reg < 16 ? 0x10 : 0;
@ -1037,7 +1136,7 @@ public abstract class AMD64BaseAssembler extends Assembler {
int p2 = 0;
p2 |= w << 7;
p2 |= ((vvvvv ^ 0x0F) & 0x0F) << 3;
p2 |= 0x4;
p2 |= 0x04;
p2 |= pp;
emitByte(p2);
@ -1050,6 +1149,11 @@ public abstract class AMD64BaseAssembler extends Assembler {
emitByte(p3);
}
/**
* Get RXB bits for register-register instructions in EVEX-encoding, where ModRM.rm contains a
* register index. The R bit extends the ModRM.reg field and the X and B bits extends the
* ModRM.rm field.
*/
private static int getRXBForEVEX(Register reg, Register rm) {
int rxb = (reg == null ? 0 : reg.encoding & 0x08) >> 1;
rxb |= (rm == null ? 0 : rm.encoding & 0x018) >> 3;
@ -1060,7 +1164,7 @@ public abstract class AMD64BaseAssembler extends Assembler {
* Helper method for emitting EVEX prefix in the form of RRRR.
*/
protected final void evexPrefix(Register dst, Register mask, Register nds, Register src, AVXSize size, int pp, int mm, int w, int z, int b) {
assert !mask.isValid() || mask.getRegisterCategory().equals(MASK);
assert !mask.isValid() || inRC(MASK, mask);
emitEVEX(getLFlag(size), pp, mm, w, getRXBForEVEX(dst, src), dst.encoding, nds.isValid() ? nds.encoding() : 0, z, b, mask.isValid() ? mask.encoding : 0);
}
@ -1071,7 +1175,7 @@ public abstract class AMD64BaseAssembler extends Assembler {
* {@link #emitEVEXOperandHelper(Register, AMD64Address, int, int)}.
*/
protected final void evexPrefix(Register dst, Register mask, Register nds, AMD64Address src, AVXSize size, int pp, int mm, int w, int z, int b) {
assert !mask.isValid() || mask.getRegisterCategory().equals(MASK);
assert !mask.isValid() || inRC(MASK, mask);
emitEVEX(getLFlag(size), pp, mm, w, getRXB(dst, src), dst.encoding, nds.isValid() ? nds.encoding() : 0, z, b, mask.isValid() ? mask.encoding : 0);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -24,6 +24,8 @@
package org.graalvm.compiler.asm.amd64;
import static jdk.vm.ci.amd64.AMD64.rbp;
import static jdk.vm.ci.amd64.AMD64.rsp;
import static org.graalvm.compiler.asm.amd64.AMD64AsmOptions.UseIncDec;
import static org.graalvm.compiler.asm.amd64.AMD64AsmOptions.UseXmmLoadAndClearUpper;
import static org.graalvm.compiler.asm.amd64.AMD64AsmOptions.UseXmmRegToRegMoveAll;
@ -82,6 +84,20 @@ public class AMD64MacroAssembler extends AMD64Assembler {
}
}
public final void enter(int frameSize) {
if (NumUtil.isUShort(frameSize)) {
// Can use enter instruction only for frame size that fits in 16 bits.
emitByte(0xC8);
emitShort(frameSize);
emitByte(0x00);
} else {
// Fall back to manual sequence.
push(rbp);
movq(rbp, rsp);
decrementq(rsp, frameSize);
}
}
public void incrementq(Register reg, int value) {
if (value == Integer.MIN_VALUE) {
addq(reg, value);

View File

@ -191,6 +191,10 @@ public class CompilationResult {
private StackSlot customStackArea = null;
/**
* A customized name that is unrelated to {@link #compilationId}. Can be null if
* {@link #compilationId} fully describes the compilation.
*/
private final String name;
private final CompilationIdentifier compilationId;
@ -228,7 +232,7 @@ public class CompilationResult {
private boolean isImmutablePIC;
public CompilationResult(CompilationIdentifier compilationId) {
this(compilationId, compilationId.toString(CompilationIdentifier.Verbosity.NAME), false);
this(compilationId, null, false);
}
public CompilationResult(CompilationIdentifier compilationId, String name) {
@ -677,6 +681,10 @@ public class CompilationResult {
return unmodifiableList(sourceMapping);
}
/**
* Gets the name for this compilation result. This will only be non-null when it provides a
* value unrelated to {@link #getCompilationId()}.
*/
public String getName() {
return name;
}

View File

@ -0,0 +1,187 @@
/*
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, Arm Limited and affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.graalvm.compiler.core.aarch64.test;
import org.graalvm.compiler.lir.aarch64.AArch64ArithmeticOp;
import org.junit.Assert;
import org.junit.Test;
public class AArch64AddSubShiftTest extends AArch64MatchRuleTest {
/**
* addSubShift match rule test for add operation with int type.
*/
private static int addLeftShiftInt(int input) {
int output = (input << 5) + input;
output += output << -5;
output += output << 32;
return output;
}
private static int addRightShiftInt(int input) {
int output = (input >> 5) + input;
output += output >> -5;
output += output >> 32;
return output;
}
private static int addUnsignedRightShiftInt(int input) {
int output = (input >>> 5) + input;
output += output >>> -5;
output += output >>> 32;
return output;
}
private static int addShiftInt(int input) {
return addLeftShiftInt(input) + addRightShiftInt(input) + addUnsignedRightShiftInt(input);
}
/**
* Check whether the addSubShift match rule in AArch64NodeMatchRules does work for add operation
* with int type and check if the expected LIR instructions show up.
*/
@Test
public void testAddShiftInt() {
int expected = addShiftInt(123);
Result result = executeActual(getResolvedJavaMethod("addShiftInt"), null, 123);
int actual = (int) result.returnValue;
Assert.assertEquals(expected, actual);
checkLIR(AArch64ArithmeticOp.AddSubShiftOp.class, 6);
}
/**
* addSubShift match rule test for add operation with long type.
*/
private static long addLeftShiftLong(long input) {
long output = (input << 5) + input;
output += output << -5;
output += output << 64;
return output;
}
private static long addRightShiftLong(long input) {
long output = (input >> 5) + input;
output += output >> -5;
output += output >> 64;
return output;
}
private static long addUnsignedRightShiftLong(long input) {
long output = (input >>> 5) + input;
output += output >>> -5;
output += output >>> 64;
return output;
}
private static long addShiftLong(long input) {
return addLeftShiftLong(input) + addRightShiftLong(input) + addUnsignedRightShiftLong(input);
}
/**
* Check whether the addSubShift match rule in AArch64NodeMatchRules does work for add operation
* with long type and check if the expected LIR instructions show up.
*/
@Test
public void testAddShiftLong() {
long expected = addShiftLong(1234567);
Result result = executeActual(getResolvedJavaMethod("addShiftLong"), null, (long) 1234567);
long actual = (long) result.returnValue;
Assert.assertEquals(expected, actual);
checkLIR(AArch64ArithmeticOp.AddSubShiftOp.class, 6);
}
/**
* addSubShift match rule test for sub operation with int type.
*/
private static int subLeftShiftInt(int input0, int input1) {
return input0 - (input1 << 5);
}
private static int subRightShiftInt(int input0, int input1) {
return input0 - (input1 >> 5);
}
private static int subUnsignedRightShiftInt(int input0, int input1) {
return input0 - (input1 >>> 5);
}
private static int subShiftInt(int input0, int input1) {
return subLeftShiftInt(input0, input1) + subRightShiftInt(input0, input1) + subUnsignedRightShiftInt(input0, input1);
}
/**
* Check whether the addSubShift match rule in AArch64NodeMatchRules does work for sub operation
* with int type and check if the expected LIR instructions show up.
*/
@Test
public void testSubShiftInt() {
int expected = subShiftInt(123, 456);
Result result = executeActual(getResolvedJavaMethod("subShiftInt"), null, 123, 456);
int actual = (int) result.returnValue;
Assert.assertEquals(expected, actual);
checkLIR(AArch64ArithmeticOp.AddSubShiftOp.class, 3);
}
/**
* addSubShift match rule test for sub operation with long type.
*/
private static long subLeftShiftLong(long input0, long input1) {
return input0 - (input1 << 5);
}
private static long subRightShiftLong(long input0, long input1) {
return input0 - (input1 >> 5);
}
private static long subUnsignedRightShiftLong(long input0, long input1) {
return input0 - (input1 >>> 5);
}
private static long subShiftLong(long input0, long input1) {
return subLeftShiftLong(input0, input1) + subRightShiftLong(input0, input1) + subUnsignedRightShiftLong(input0, input1);
}
/**
* Check whether the addSubShift match rule in AArch64NodeMatchRules does work for sub operation
* with long type and check if the expected LIR instructions show up.
*/
@Test
public void testSubShiftLong() {
long expected = subShiftLong(1234567, 123);
Result result = executeActual(getResolvedJavaMethod("subShiftLong"), null, (long) 1234567, (long) 123);
long actual = (long) result.returnValue;
Assert.assertEquals(expected, actual);
checkLIR(AArch64ArithmeticOp.AddSubShiftOp.class, 3);
}
}

View File

@ -0,0 +1,77 @@
/*
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, Arm Limited and affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.graalvm.compiler.core.aarch64.test;
import jdk.vm.ci.aarch64.AArch64;
import jdk.vm.ci.code.TargetDescription;
import org.graalvm.compiler.core.test.GraalCompilerTest;
import org.graalvm.compiler.lir.LIR;
import org.graalvm.compiler.lir.LIRInstruction;
import org.graalvm.compiler.lir.aarch64.AArch64LIRInstruction;
import org.graalvm.compiler.lir.gen.LIRGenerationResult;
import org.graalvm.compiler.lir.phases.LIRPhase;
import org.graalvm.compiler.lir.phases.LIRSuites;
import org.graalvm.compiler.lir.phases.PreAllocationOptimizationPhase;
import org.graalvm.compiler.options.OptionValues;
import org.junit.Assert;
import org.junit.Before;
import static org.junit.Assume.assumeTrue;
public abstract class AArch64MatchRuleTest extends GraalCompilerTest {
private LIR lir;
@Before
public void checkAArch64() {
assumeTrue("skipping AArch64 specific test", getTarget().arch instanceof AArch64);
}
@Override
protected LIRSuites createLIRSuites(OptionValues options) {
LIRSuites suites = super.createLIRSuites(options);
suites.getPreAllocationOptimizationStage().appendPhase(new CheckPhase());
return suites;
}
private class CheckPhase extends LIRPhase<PreAllocationOptimizationPhase.PreAllocationOptimizationContext> {
@Override
protected void run(TargetDescription target, LIRGenerationResult lirGenRes,
PreAllocationOptimizationPhase.PreAllocationOptimizationContext context) {
lir = lirGenRes.getLIR();
}
}
protected void checkLIR(Class<? extends AArch64LIRInstruction> op, int expected) {
int actualOpNum = 0;
for (LIRInstruction ins : lir.getLIRforBlock(lir.codeEmittingOrder()[0])) {
if (ins.getClass() == op) {
actualOpNum++;
}
}
Assert.assertEquals(expected, actualOpNum);
}
}

View File

@ -201,6 +201,16 @@ public class AArch64ArithmeticLIRGenerator extends ArithmeticLIRGenerator implem
return result;
}
public Value emitAddSubShift(AArch64ArithmeticOp op, Value a, Value b, AArch64MacroAssembler.ShiftType shiftType, int shiftAmount) {
assert isNumericInteger(a.getPlatformKind());
assert isNumericInteger(b.getPlatformKind());
Variable result = getLIRGen().newVariable(LIRKind.combine(a, b));
AllocatableValue x = moveSp(asAllocatable(a));
AllocatableValue y = moveSp(asAllocatable(b));
getLIRGen().append(new AArch64ArithmeticOp.AddSubShiftOp(op, result, x, y, shiftType, shiftAmount));
return result;
}
private static PlatformKind getFloatConvertResultKind(FloatConvert op) {
switch (op) {
case F2I:

View File

@ -61,6 +61,7 @@ import org.graalvm.compiler.lir.aarch64.AArch64AtomicMove.CompareAndSwapOp;
import org.graalvm.compiler.lir.aarch64.AArch64AtomicMove.AtomicReadAndWriteOp;
import org.graalvm.compiler.lir.aarch64.AArch64Move.MembarOp;
import org.graalvm.compiler.lir.aarch64.AArch64PauseOp;
import org.graalvm.compiler.lir.aarch64.AArch64SpeculativeBarrier;
import org.graalvm.compiler.lir.gen.LIRGenerationResult;
import org.graalvm.compiler.lir.gen.LIRGenerator;
import org.graalvm.compiler.phases.util.Providers;
@ -465,9 +466,9 @@ public abstract class AArch64LIRGenerator extends LIRGenerator {
}
@Override
public Variable emitArrayEquals(JavaKind kind, Value array1, Value array2, Value length) {
public Variable emitArrayEquals(JavaKind kind, Value array1, Value array2, Value length, int constantLength, boolean directPointers) {
Variable result = newVariable(LIRKind.value(AArch64Kind.DWORD));
append(new AArch64ArrayEqualsOp(this, kind, result, array1, array2, asAllocatable(length)));
append(new AArch64ArrayEqualsOp(this, kind, result, array1, array2, asAllocatable(length), directPointers));
return result;
}
@ -513,4 +514,9 @@ public abstract class AArch64LIRGenerator extends LIRGenerator {
}
public abstract void emitCCall(long address, CallingConvention nativeCallingConvention, Value[] args);
@Override
public void emitSpeculationFence() {
append(new AArch64SpeculativeBarrier());
}
}

View File

@ -34,6 +34,7 @@ import org.graalvm.compiler.core.common.type.DataPointerConstant;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.lir.LIRInstruction;
import org.graalvm.compiler.lir.aarch64.AArch64AddressValue;
import org.graalvm.compiler.lir.aarch64.AArch64LIRInstruction;
import org.graalvm.compiler.lir.aarch64.AArch64Move;
import org.graalvm.compiler.lir.aarch64.AArch64Move.LoadAddressOp;
import org.graalvm.compiler.lir.gen.LIRGeneratorTool.MoveFactory;
@ -69,7 +70,7 @@ public class AArch64MoveFactory implements MoveFactory {
}
@Override
public LIRInstruction createLoad(AllocatableValue dst, Constant src) {
public AArch64LIRInstruction createLoad(AllocatableValue dst, Constant src) {
if (src instanceof JavaConstant) {
JavaConstant javaConstant = (JavaConstant) src;
if (canInlineConstant(javaConstant)) {

View File

@ -25,11 +25,22 @@
package org.graalvm.compiler.core.aarch64;
import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler;
import org.graalvm.compiler.core.gen.NodeMatchRules;
import org.graalvm.compiler.core.match.ComplexMatchResult;
import org.graalvm.compiler.core.match.MatchRule;
import org.graalvm.compiler.lir.LIRFrameState;
import org.graalvm.compiler.lir.aarch64.AArch64ArithmeticOp;
import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
import org.graalvm.compiler.nodes.ConstantNode;
import org.graalvm.compiler.nodes.DeoptimizingNode;
import org.graalvm.compiler.nodes.NodeView;
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.calc.AddNode;
import org.graalvm.compiler.nodes.calc.BinaryNode;
import org.graalvm.compiler.nodes.calc.LeftShiftNode;
import org.graalvm.compiler.nodes.calc.RightShiftNode;
import org.graalvm.compiler.nodes.calc.UnsignedRightShiftNode;
import org.graalvm.compiler.nodes.memory.Access;
import jdk.vm.ci.aarch64.AArch64Kind;
@ -51,6 +62,36 @@ public class AArch64NodeMatchRules extends NodeMatchRules {
return (AArch64Kind) gen.getLIRKind(access.asNode().stamp(NodeView.DEFAULT)).getPlatformKind();
}
private ComplexMatchResult emitAddSubShift(AArch64ArithmeticOp op, ValueNode value, BinaryNode shift) {
assert shift.getY() instanceof ConstantNode;
int shiftAmount = shift.getY().asJavaConstant().asInt();
if (shift instanceof LeftShiftNode) {
return builder -> getArithmeticLIRGenerator().emitAddSubShift(op, operand(value), operand(shift.getX()),
AArch64MacroAssembler.ShiftType.LSL, shiftAmount);
} else if (shift instanceof RightShiftNode) {
return builder -> getArithmeticLIRGenerator().emitAddSubShift(op, operand(value), operand(shift.getX()),
AArch64MacroAssembler.ShiftType.ASR, shiftAmount);
} else {
assert shift instanceof UnsignedRightShiftNode;
return builder -> getArithmeticLIRGenerator().emitAddSubShift(op, operand(value), operand(shift.getX()),
AArch64MacroAssembler.ShiftType.LSR, shiftAmount);
}
}
@MatchRule("(Add=binary a (LeftShift=shift b Constant))")
@MatchRule("(Add=binary a (RightShift=shift b Constant))")
@MatchRule("(Add=binary a (UnsignedRightShift=shift b Constant))")
@MatchRule("(Sub=binary a (LeftShift=shift b Constant))")
@MatchRule("(Sub=binary a (RightShift=shift b Constant))")
@MatchRule("(Sub=binary a (UnsignedRightShift=shift b Constant))")
public ComplexMatchResult addSubShift(BinaryNode binary, ValueNode a, BinaryNode shift) {
if (binary instanceof AddNode) {
return emitAddSubShift(AArch64ArithmeticOp.ADD, a, shift);
}
return emitAddSubShift(AArch64ArithmeticOp.SUB, a, shift);
}
@Override
public AArch64LIRGenerator getLIRGeneratorTool() {
return (AArch64LIRGenerator) gen;

View File

@ -84,7 +84,10 @@ import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RMIOp;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RMOp;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64Shift;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.SSEOp;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.VexGeneralPurposeRVMOp;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.VexGeneralPurposeRMOp;
import org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize;
import org.graalvm.compiler.asm.amd64.AVXKind.AVXSize;
import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.core.common.NumUtil;
import org.graalvm.compiler.core.common.calc.FloatConvert;
@ -106,6 +109,8 @@ import org.graalvm.compiler.lir.amd64.AMD64MulDivOp;
import org.graalvm.compiler.lir.amd64.AMD64ShiftOp;
import org.graalvm.compiler.lir.amd64.AMD64SignExtendOp;
import org.graalvm.compiler.lir.amd64.AMD64Unary;
import org.graalvm.compiler.lir.amd64.vector.AMD64VectorBinary;
import org.graalvm.compiler.lir.amd64.vector.AMD64VectorUnary;
import org.graalvm.compiler.lir.gen.ArithmeticLIRGenerator;
import org.graalvm.compiler.lir.gen.LIRGenerator;
@ -931,6 +936,57 @@ public class AMD64ArithmeticLIRGenerator extends ArithmeticLIRGenerator implemen
return result;
}
@Override
public Value emitLogicalAndNot(Value value1, Value value2) {
Variable result = getLIRGen().newVariable(LIRKind.combine(value1, value2));
if (value1.getPlatformKind() == AMD64Kind.QWORD) {
getLIRGen().append(new AMD64VectorBinary.AVXBinaryOp(VexGeneralPurposeRVMOp.ANDN, AVXSize.QWORD, result, asAllocatable(value1), asAllocatable(value2)));
} else {
getLIRGen().append(new AMD64VectorBinary.AVXBinaryOp(VexGeneralPurposeRVMOp.ANDN, AVXSize.DWORD, result, asAllocatable(value1), asAllocatable(value2)));
}
return result;
}
@Override
public Value emitLowestSetIsolatedBit(Value value) {
Variable result = getLIRGen().newVariable(LIRKind.combine(value));
if (value.getPlatformKind() == AMD64Kind.QWORD) {
getLIRGen().append(new AMD64VectorUnary.AVXUnaryOp(VexGeneralPurposeRMOp.BLSI, AVXSize.QWORD, result, asAllocatable(value)));
} else {
getLIRGen().append(new AMD64VectorUnary.AVXUnaryOp(VexGeneralPurposeRMOp.BLSI, AVXSize.DWORD, result, asAllocatable(value)));
}
return result;
}
@Override
public Value emitGetMaskUpToLowestSetBit(Value value) {
Variable result = getLIRGen().newVariable(LIRKind.combine(value));
if (value.getPlatformKind() == AMD64Kind.QWORD) {
getLIRGen().append(new AMD64VectorUnary.AVXUnaryOp(VexGeneralPurposeRMOp.BLSMSK, AVXSize.QWORD, result, asAllocatable(value)));
} else {
getLIRGen().append(new AMD64VectorUnary.AVXUnaryOp(VexGeneralPurposeRMOp.BLSMSK, AVXSize.DWORD, result, asAllocatable(value)));
}
return result;
}
@Override
public Value emitResetLowestSetBit(Value value) {
Variable result = getLIRGen().newVariable(LIRKind.combine(value));
if (value.getPlatformKind() == AMD64Kind.QWORD) {
getLIRGen().append(new AMD64VectorUnary.AVXUnaryOp(VexGeneralPurposeRMOp.BLSR, AVXSize.QWORD, result, asAllocatable(value)));
} else {
getLIRGen().append(new AMD64VectorUnary.AVXUnaryOp(VexGeneralPurposeRMOp.BLSR, AVXSize.DWORD, result, asAllocatable(value)));
}
return result;
}
@Override
public Value emitMathAbs(Value input) {
Variable result = getLIRGen().newVariable(LIRKind.combine(input));

View File

@ -87,7 +87,8 @@ import org.graalvm.compiler.lir.amd64.AMD64Move.CompareAndSwapOp;
import org.graalvm.compiler.lir.amd64.AMD64Move.MembarOp;
import org.graalvm.compiler.lir.amd64.AMD64Move.StackLeaOp;
import org.graalvm.compiler.lir.amd64.AMD64PauseOp;
import org.graalvm.compiler.lir.amd64.AMD64StringIndexOfOp;
import org.graalvm.compiler.lir.amd64.AMD64StringLatin1InflateOp;
import org.graalvm.compiler.lir.amd64.AMD64StringUTF16CompressOp;
import org.graalvm.compiler.lir.amd64.AMD64ZapRegistersOp;
import org.graalvm.compiler.lir.amd64.AMD64ZapStackOp;
import org.graalvm.compiler.lir.gen.LIRGenerationResult;
@ -262,8 +263,8 @@ public abstract class AMD64LIRGenerator extends LIRGenerator {
public void emitCompareAndSwapBranch(ValueKind<?> kind, AMD64AddressValue address, Value expectedValue, Value newValue, Condition condition, LabelRef trueLabel, LabelRef falseLabel,
double trueLabelProbability) {
assert kind.equals(expectedValue.getValueKind());
assert kind.equals(newValue.getValueKind());
assert kind.getPlatformKind().getSizeInBytes() <= expectedValue.getValueKind().getPlatformKind().getSizeInBytes();
assert kind.getPlatformKind().getSizeInBytes() <= newValue.getValueKind().getPlatformKind().getSizeInBytes();
assert condition == Condition.EQ || condition == Condition.NE;
AMD64Kind memKind = (AMD64Kind) kind.getPlatformKind();
RegisterValue raxValue = AMD64.rax.asValue(kind);
@ -542,9 +543,9 @@ public abstract class AMD64LIRGenerator extends LIRGenerator {
}
@Override
public Variable emitArrayEquals(JavaKind kind, Value array1, Value array2, Value length) {
public Variable emitArrayEquals(JavaKind kind, Value array1, Value array2, Value length, int constantLength, boolean directPointers) {
Variable result = newVariable(LIRKind.value(AMD64Kind.DWORD));
append(new AMD64ArrayEqualsOp(this, kind, result, array1, array2, asAllocatable(length)));
append(new AMD64ArrayEqualsOp(this, kind, result, array1, array2, asAllocatable(length), constantLength, directPointers, getMaxVectorSize()));
return result;
}
@ -555,22 +556,56 @@ public abstract class AMD64LIRGenerator extends LIRGenerator {
return 4096;
}
/**
* Return the maximum size of vector registers used in SSE/AVX instructions.
*/
protected int getMaxVectorSize() {
// default for "unlimited"
return -1;
}
@Override
public Variable emitStringIndexOf(Value source, Value sourceCount, Value target, Value targetCount, int constantTargetCount) {
Variable result = newVariable(LIRKind.value(AMD64Kind.DWORD));
RegisterValue cnt1 = AMD64.rdx.asValue(sourceCount.getValueKind());
emitMove(cnt1, sourceCount);
RegisterValue cnt2 = AMD64.rax.asValue(targetCount.getValueKind());
emitMove(cnt2, targetCount);
append(new AMD64StringIndexOfOp(this, result, source, target, cnt1, cnt2, AMD64.rcx.asValue(), AMD64.xmm0.asValue(), constantTargetCount, getVMPageSize()));
public Variable emitArrayIndexOf(JavaKind kind, boolean findTwoConsecutive, Value arrayPointer, Value arrayLength, Value... searchValues) {
Variable result = newVariable(LIRKind.value(AMD64Kind.QWORD));
Value[] allocatableSearchValues = new Value[searchValues.length];
for (int i = 0; i < searchValues.length; i++) {
allocatableSearchValues[i] = asAllocatable(searchValues[i]);
}
append(new AMD64ArrayIndexOfOp(kind, findTwoConsecutive, getVMPageSize(), getMaxVectorSize(), this, result, asAllocatable(arrayPointer), asAllocatable(arrayLength), allocatableSearchValues));
return result;
}
@Override
public Variable emitArrayIndexOf(JavaKind kind, Value arrayPointer, Value arrayLength, Value charValue) {
Variable result = newVariable(LIRKind.value(AMD64Kind.DWORD));
append(new AMD64ArrayIndexOfOp(kind, getVMPageSize(), this, result, asAllocatable(arrayPointer), asAllocatable(arrayLength), asAllocatable(charValue)));
return result;
public void emitStringLatin1Inflate(Value src, Value dst, Value len) {
RegisterValue rsrc = AMD64.rsi.asValue(src.getValueKind());
RegisterValue rdst = AMD64.rdi.asValue(dst.getValueKind());
RegisterValue rlen = AMD64.rdx.asValue(len.getValueKind());
emitMove(rsrc, src);
emitMove(rdst, dst);
emitMove(rlen, len);
append(new AMD64StringLatin1InflateOp(this, rsrc, rdst, rlen));
}
@Override
public Variable emitStringUTF16Compress(Value src, Value dst, Value len) {
RegisterValue rsrc = AMD64.rsi.asValue(src.getValueKind());
RegisterValue rdst = AMD64.rdi.asValue(dst.getValueKind());
RegisterValue rlen = AMD64.rdx.asValue(len.getValueKind());
emitMove(rsrc, src);
emitMove(rdst, dst);
emitMove(rlen, len);
LIRKind reskind = LIRKind.value(AMD64Kind.DWORD);
RegisterValue rres = AMD64.rax.asValue(reskind);
append(new AMD64StringUTF16CompressOp(this, rres, rsrc, rdst, rlen));
Variable res = newVariable(reskind);
emitMove(res, rres);
return res;
}
@Override
@ -614,7 +649,8 @@ public abstract class AMD64LIRGenerator extends LIRGenerator {
return new AMD64ZapStackOp(zappedStack, zapValues);
}
public void emitLFence() {
@Override
public void emitSpeculationFence() {
append(new AMD64LFenceOp());
}
}

View File

@ -25,8 +25,6 @@
package org.graalvm.compiler.core.amd64;
import static org.graalvm.compiler.core.amd64.AMD64NodeLIRBuilder.Options.MitigateSpeculativeExecutionAttacks;
import org.graalvm.compiler.core.gen.NodeLIRBuilder;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.lir.LIRFrameState;
@ -41,11 +39,6 @@ import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.calc.IntegerDivRemNode;
import org.graalvm.compiler.nodes.calc.IntegerDivRemNode.Op;
import org.graalvm.compiler.nodes.cfg.Block;
import org.graalvm.compiler.options.Option;
import org.graalvm.compiler.options.OptionKey;
import org.graalvm.compiler.options.OptionType;
import org.graalvm.compiler.options.OptionValues;
import jdk.vm.ci.amd64.AMD64;
import jdk.vm.ci.meta.AllocatableValue;
@ -53,13 +46,6 @@ import jdk.vm.ci.meta.Value;
public abstract class AMD64NodeLIRBuilder extends NodeLIRBuilder {
public static class Options {
// @formatter:off
@Option(help = "AMD64: Emit lfence instructions at the beginning of basic blocks", type = OptionType.Expert)
public static final OptionKey<Boolean> MitigateSpeculativeExecutionAttacks = new OptionKey<>(false);
// @formatter:on
}
public AMD64NodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool gen, AMD64NodeMatchRules nodeMatchRules) {
super(graph, gen, nodeMatchRules);
}
@ -137,21 +123,4 @@ public abstract class AMD64NodeLIRBuilder extends NodeLIRBuilder {
public AMD64LIRGenerator getLIRGeneratorTool() {
return (AMD64LIRGenerator) gen;
}
@Override
public void doBlockPrologue(Block block, OptionValues options) {
if (MitigateSpeculativeExecutionAttacks.getValue(options)) {
boolean hasControlSplitPredecessor = false;
for (Block b : block.getPredecessors()) {
if (b.getSuccessorCount() > 1) {
hasControlSplitPredecessor = true;
break;
}
}
boolean isStartBlock = block.getPredecessorCount() == 0;
if (hasControlSplitPredecessor || isStartBlock) {
getLIRGeneratorTool().emitLFence();
}
}
}
}

View File

@ -78,9 +78,12 @@ import org.graalvm.compiler.nodes.memory.LIRLowerableAccess;
import org.graalvm.compiler.nodes.memory.WriteNode;
import org.graalvm.compiler.nodes.util.GraphUtil;
import jdk.vm.ci.amd64.AMD64;
import jdk.vm.ci.amd64.AMD64.CPUFeature;
import jdk.vm.ci.amd64.AMD64Kind;
import jdk.vm.ci.meta.AllocatableValue;
import jdk.vm.ci.meta.JavaConstant;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.PlatformKind;
import jdk.vm.ci.meta.Value;
import jdk.vm.ci.meta.ValueKind;
@ -272,6 +275,81 @@ public class AMD64NodeMatchRules extends NodeMatchRules {
return getArithmeticLIRGenerator().emitLoad(to, address, state);
}
private boolean supports(CPUFeature feature) {
return ((AMD64) getLIRGeneratorTool().target().arch).getFeatures().contains(feature);
}
@MatchRule("(And (Not a) b)")
public ComplexMatchResult logicalAndNot(ValueNode a, ValueNode b) {
if (!supports(CPUFeature.BMI1)) {
return null;
}
return builder -> getArithmeticLIRGenerator().emitLogicalAndNot(operand(a), operand(b));
}
@MatchRule("(And a (Negate a))")
public ComplexMatchResult lowestSetIsolatedBit(ValueNode a) {
if (!supports(CPUFeature.BMI1)) {
return null;
}
return builder -> getArithmeticLIRGenerator().emitLowestSetIsolatedBit(operand(a));
}
@MatchRule("(Xor a (Add a b))")
public ComplexMatchResult getMaskUpToLowestSetBit(ValueNode a, ValueNode b) {
if (!supports(CPUFeature.BMI1)) {
return null;
}
// Make sure that the pattern matches a subtraction by one.
if (!b.isJavaConstant()) {
return null;
}
JavaConstant bCst = b.asJavaConstant();
long bValue;
if (bCst.getJavaKind() == JavaKind.Int) {
bValue = bCst.asInt();
} else if (bCst.getJavaKind() == JavaKind.Long) {
bValue = bCst.asLong();
} else {
return null;
}
if (bValue == -1) {
return builder -> getArithmeticLIRGenerator().emitGetMaskUpToLowestSetBit(operand(a));
} else {
return null;
}
}
@MatchRule("(And a (Add a b))")
public ComplexMatchResult resetLowestSetBit(ValueNode a, ValueNode b) {
if (!supports(CPUFeature.BMI1)) {
return null;
}
// Make sure that the pattern matches a subtraction by one.
if (!b.isJavaConstant()) {
return null;
}
JavaConstant bCst = b.asJavaConstant();
long bValue;
if (bCst.getJavaKind() == JavaKind.Int) {
bValue = bCst.asInt();
} else if (bCst.getJavaKind() == JavaKind.Long) {
bValue = bCst.asLong();
} else {
return null;
}
if (bValue == -1) {
return builder -> getArithmeticLIRGenerator().emitResetLowestSetBit(operand(a));
} else {
return null;
}
}
@MatchRule("(If (IntegerTest Read=access value))")
@MatchRule("(If (IntegerTest FloatingRead=access value))")
public ComplexMatchResult integerTestBranchMemory(IfNode root, LIRLowerableAccess access, ValueNode value) {

View File

@ -215,14 +215,14 @@ public class NumUtil {
}
public static long maxUnsigned(long a, long b) {
if (Long.compareUnsigned(a, b) > 0) {
if (Long.compareUnsigned(a, b) < 0) {
return b;
}
return a;
}
public static long minUnsigned(long a, long b) {
if (Long.compareUnsigned(a, b) > 0) {
if (Long.compareUnsigned(a, b) < 0) {
return a;
}
return b;

View File

@ -0,0 +1,46 @@
/*
* Copyright (c) 2018, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.graalvm.compiler.core.common;
import org.graalvm.compiler.options.EnumOptionKey;
import org.graalvm.compiler.options.Option;
import org.graalvm.compiler.options.OptionKey;
import org.graalvm.compiler.options.OptionType;
public enum SpeculativeExecutionAttacksMitigations {
None,
AllTargets,
GuardTargets,
NonDeoptGuardTargets;
public static class Options {
// @formatter:off
@Option(help = "Select a strategy to mitigate speculative execution attacks (e.g., SPECTRE)", type = OptionType.User)
public static final EnumOptionKey<SpeculativeExecutionAttacksMitigations> MitigateSpeculativeExecutionAttacks = new EnumOptionKey<>(None);
@Option(help = "Use index masking after bounds check to mitigate speculative execution attacks", type = OptionType.User)
public static final OptionKey<Boolean> UseIndexMasking = new OptionKey<>(false);
// @formatter:on
}
}

View File

@ -63,7 +63,7 @@ public final class BiDirectionalTraceBuilder {
}
private static int compare(AbstractBlockBase<?> a, AbstractBlockBase<?> b) {
return Double.compare(b.probability(), a.probability());
return Double.compare(b.getRelativeFrequency(), a.getRelativeFrequency());
}
private boolean processed(AbstractBlockBase<?> b) {
@ -132,7 +132,7 @@ public final class BiDirectionalTraceBuilder {
}
private void addBlockToTrace(DebugContext debug, AbstractBlockBase<?> block) {
debug.log("add %s (prob: %f)", block, block.probability());
debug.log("add %s (freq: %f)", block, block.getRelativeFrequency());
processed.set(block.getId());
}
@ -142,7 +142,7 @@ public final class BiDirectionalTraceBuilder {
private AbstractBlockBase<?> selectPredecessor(AbstractBlockBase<?> block) {
AbstractBlockBase<?> next = null;
for (AbstractBlockBase<?> pred : block.getPredecessors()) {
if (!processed(pred) && !isBackEdge(pred, block) && (next == null || pred.probability() > next.probability())) {
if (!processed(pred) && !isBackEdge(pred, block) && (next == null || pred.getRelativeFrequency() > next.getRelativeFrequency())) {
next = pred;
}
}
@ -160,7 +160,7 @@ public final class BiDirectionalTraceBuilder {
private AbstractBlockBase<?> selectSuccessor(AbstractBlockBase<?> block) {
AbstractBlockBase<?> next = null;
for (AbstractBlockBase<?> succ : block.getSuccessors()) {
if (!processed(succ) && (next == null || succ.probability() > next.probability())) {
if (!processed(succ) && (next == null || succ.getRelativeFrequency() > next.getRelativeFrequency())) {
next = succ;
}
}

View File

@ -143,11 +143,11 @@ public final class ComputeBlockOrder {
double unscheduledSum = 0.0;
for (T pred : mostLikelySuccessor.getPredecessors()) {
if (pred.getLinearScanNumber() == -1) {
unscheduledSum += pred.probability();
unscheduledSum += pred.getRelativeFrequency();
}
}
if (unscheduledSum > block.probability() / PENALTY_VERSUS_UNSCHEDULED) {
if (unscheduledSum > block.getRelativeFrequency() / PENALTY_VERSUS_UNSCHEDULED) {
// Add this merge only after at least one additional predecessor gets scheduled.
visitedBlocks.clear(mostLikelySuccessor.getId());
return null;
@ -212,8 +212,8 @@ public final class ComputeBlockOrder {
private static <T extends AbstractBlockBase<T>> T findAndMarkMostLikelySuccessor(T block, BitSet visitedBlocks) {
T result = null;
for (T successor : block.getSuccessors()) {
assert successor.probability() >= 0.0 : "Probabilities must be positive";
if (!visitedBlocks.get(successor.getId()) && successor.getLoopDepth() >= block.getLoopDepth() && (result == null || successor.probability() >= result.probability())) {
assert successor.getRelativeFrequency() >= 0.0 : "Relative frequencies must be positive";
if (!visitedBlocks.get(successor.getId()) && successor.getLoopDepth() >= block.getLoopDepth() && (result == null || successor.getRelativeFrequency() >= result.getRelativeFrequency())) {
result = successor;
}
}
@ -261,7 +261,7 @@ public final class ComputeBlockOrder {
public int compare(T a, T b) {
// Loop blocks before any loop exit block. The only exception are blocks that are
// (almost) impossible to reach.
if (a.probability() > EPSILON && b.probability() > EPSILON) {
if (a.getRelativeFrequency() > EPSILON && b.getRelativeFrequency() > EPSILON) {
int diff = b.getLoopDepth() - a.getLoopDepth();
if (diff != 0) {
return diff;
@ -269,7 +269,7 @@ public final class ComputeBlockOrder {
}
// Blocks with high probability before blocks with low probability.
if (a.probability() > b.probability()) {
if (a.getRelativeFrequency() > b.getRelativeFrequency()) {
return -1;
} else {
return 1;

View File

@ -59,13 +59,13 @@ public final class TraceStatisticsPrinter {
double max = Double.NEGATIVE_INFINITY;
double min = Double.POSITIVE_INFINITY;
for (AbstractBlockBase<?> block : t) {
double probability = block.probability();
total += probability;
if (probability < min) {
min = probability;
double frequency = block.getRelativeFrequency();
total += frequency;
if (frequency < min) {
min = frequency;
}
if (probability > max) {
max = probability;
if (frequency > max) {
max = frequency;
}
}
printLine(debug, i, total, min, max, t.length);

View File

@ -65,7 +65,7 @@ public final class UniDirectionalTraceBuilder {
}
private static int compare(AbstractBlockBase<?> a, AbstractBlockBase<?> b) {
return Double.compare(b.probability(), a.probability());
return Double.compare(b.getRelativeFrequency(), a.getRelativeFrequency());
}
private boolean processed(AbstractBlockBase<?> b) {
@ -110,7 +110,7 @@ public final class UniDirectionalTraceBuilder {
int blockNumber = 0;
try (Indent i = debug.logAndIndent("StartTrace: %s", traceStart)) {
for (AbstractBlockBase<?> block = traceStart; block != null; block = selectNext(block)) {
debug.log("add %s (prob: %f)", block, block.probability());
debug.log("add %s (freq: %f)", block, block.getRelativeFrequency());
processed.set(block.getId());
trace.add(block);
unblock(block);
@ -149,7 +149,7 @@ public final class UniDirectionalTraceBuilder {
private AbstractBlockBase<?> selectNext(AbstractBlockBase<?> block) {
AbstractBlockBase<?> next = null;
for (AbstractBlockBase<?> successor : block.getSuccessors()) {
if (!processed(successor) && (next == null || successor.probability() > next.probability())) {
if (!processed(successor) && (next == null || successor.getRelativeFrequency() > next.getRelativeFrequency())) {
next = successor;
}
}

View File

@ -163,7 +163,7 @@ public abstract class AbstractBlockBase<T extends AbstractBlockBase<T>> {
public abstract T getPostdominator();
public abstract double probability();
public abstract double getRelativeFrequency();
public abstract T getDominator(int distance);

View File

@ -41,6 +41,4 @@ public interface CodeGenProviders {
ForeignCallsProvider getForeignCalls();
ConstantReflectionProvider getConstantReflection();
ArrayOffsetProvider getArrayOffsetProvider();
}

View File

@ -142,10 +142,13 @@ public abstract class AbstractPointerStamp extends Stamp {
@Override
public Constant asConstant() {
if (alwaysNull) {
return JavaConstant.NULL_POINTER;
} else {
return null;
return nullConstant();
}
return super.asConstant();
}
public JavaConstant nullConstant() {
return JavaConstant.NULL_POINTER;
}
@Override

View File

@ -0,0 +1,342 @@
/*
* Copyright (c) 2018, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.graalvm.compiler.core.jdk9.test.ea;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicReference;
import org.graalvm.compiler.core.test.ea.EATestBase;
import org.junit.Test;
import jdk.vm.ci.meta.JavaConstant;
public class AtomicVirtualizationTests extends EATestBase {
private static final TestObject OBJ1 = new TestObject(1);
private static final TestObject OBJ2 = new TestObject(2);
private static TestObject obj6 = new TestObject(6);
private static TestObject obj7 = new TestObject(7);
private static TestObject obj8 = new TestObject(8);
private static final class TestObject {
final int id;
private TestObject(int id) {
this.id = id;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
TestObject that = (TestObject) o;
return id == that.id;
}
@Override
public int hashCode() {
return Objects.hash(id);
}
@Override
public String toString() {
return "TestObject{id=" + id + '}';
}
}
// c = constant (heap-allocated); v = virtual; u = unknown (heap-allocated)
public static boolean cvvNoMatchCAS() {
AtomicReference<TestObject> a = new AtomicReference<>(null);
return a.compareAndSet(new TestObject(3), new TestObject(4));
}
@Test
public void testcvvNoMatchCAS() {
testAtomicVirtualization("cvvNoMatchCAS", JavaConstant.INT_0);
}
public static Object cvvNoMatchCAE() {
AtomicReference<TestObject> a = new AtomicReference<>(null);
return a.compareAndExchange(new TestObject(3), new TestObject(4));
}
@Test
public void testcvvNoMatchCAE() {
testAtomicVirtualization("cvvNoMatchCAE", JavaConstant.NULL_POINTER);
}
public static boolean ccvNoMatchCAS() {
AtomicReference<TestObject> a = new AtomicReference<>(null);
return a.compareAndSet(OBJ1, new TestObject(3));
}
@Test
public void testccvNoMatchCAS() {
testAtomicVirtualization("ccvNoMatchCAS", JavaConstant.INT_0);
}
public static Object ccvNoMatchCAE() {
AtomicReference<TestObject> a = new AtomicReference<>(null);
return a.compareAndExchange(OBJ1, new TestObject(3));
}
@Test
public void testccvNoMatchCAE() {
testAtomicVirtualization("ccvNoMatchCAE", JavaConstant.NULL_POINTER);
}
public static boolean cccNoMatchCAS() {
AtomicReference<TestObject> a = new AtomicReference<>(null);
return a.compareAndSet(OBJ1, OBJ2);
}
@Test
public void testcccNoMatchCAS() {
testAtomicVirtualization("cccNoMatchCAS", JavaConstant.INT_0);
}
public static Object cccNoMatchCAE() {
AtomicReference<TestObject> a = new AtomicReference<>(null);
return a.compareAndExchange(OBJ1, OBJ2);
}
@Test
public void testcccNoMatchCAE() {
testAtomicVirtualization("cccNoMatchCAE", JavaConstant.NULL_POINTER);
}
public static boolean ccvCAS() {
AtomicReference<TestObject> a = new AtomicReference<>(null);
return a.compareAndSet(null, new TestObject(3));
}
@Test
public void testccvCAS() {
testAtomicVirtualization("ccvCAS", JavaConstant.INT_1);
}
public static Object ccvCAE() {
AtomicReference<TestObject> a = new AtomicReference<>(null);
return a.compareAndExchange(null, new TestObject(3));
}
@Test
public void testccvCAE() {
testAtomicVirtualization("ccvCAE", null, 0);
}
public static boolean cccCAS() {
AtomicReference<TestObject> a = new AtomicReference<>(null);
return a.compareAndSet(null, OBJ2);
}
@Test
public void testcccCAS() {
testAtomicVirtualization("cccCAS", JavaConstant.INT_1);
}
public static Object cccCAE() {
AtomicReference<TestObject> a = new AtomicReference<>(null);
return a.compareAndExchange(null, OBJ2);
}
@Test
public void testcccCAE() {
testAtomicVirtualization("cccCAE", null);
}
public static boolean vvvNoMatchCAS() {
AtomicReference<TestObject> a = new AtomicReference<>(new TestObject(3));
return a.compareAndSet(new TestObject(4), new TestObject(5));
}
@Test
public void testvvvNoMatchCAS() {
testAtomicVirtualization("vvvNoMatchCAS", JavaConstant.INT_0);
}
public static Object vvvNoMatchCAE() {
AtomicReference<TestObject> a = new AtomicReference<>(new TestObject(3));
return a.compareAndExchange(new TestObject(4), new TestObject(5));
}
@Test
public void testvvvNoMatchCAE() {
testAtomicVirtualization("vvvNoMatchCAE", null, 1);
}
public static boolean vcvNoMatchCAS() {
AtomicReference<TestObject> a = new AtomicReference<>(new TestObject(3));
return a.compareAndSet(OBJ1, new TestObject(4));
}
@Test
public void testvcvNoMatchCAS() {
testAtomicVirtualization("vcvNoMatchCAS", JavaConstant.INT_0);
}
public static Object vcvNoMatchCAE() {
AtomicReference<TestObject> a = new AtomicReference<>(new TestObject(3));
return a.compareAndExchange(OBJ1, new TestObject(4));
}
@Test
public void testvcvNoMatchCAE() {
testAtomicVirtualization("vcvNoMatchCAE", null, 1);
}
public static boolean vccNoMatchCAS() {
AtomicReference<TestObject> a = new AtomicReference<>(new TestObject(3));
return a.compareAndSet(OBJ1, OBJ2);
}
@Test
public void testvccNoMatchCAS() {
testAtomicVirtualization("vccNoMatchCAS", JavaConstant.INT_0);
}
public static Object vccNoMatchCAE() {
AtomicReference<TestObject> a = new AtomicReference<>(new TestObject(3));
return a.compareAndExchange(OBJ1, OBJ2);
}
@Test
public void testvccNoMatchCAE() {
testAtomicVirtualization("vccNoMatchCAE", null, 1);
}
public static boolean uvvCAS() {
AtomicReference<TestObject> a = new AtomicReference<>(obj6);
return a.compareAndSet(new TestObject(3), new TestObject(4));
}
@Test
public void testuvvCAS() {
testAtomicVirtualization("uvvCAS", JavaConstant.INT_0);
}
public static Object uvvCAE() {
AtomicReference<TestObject> a = new AtomicReference<>(obj6);
return a.compareAndExchange(new TestObject(3), new TestObject(4));
}
@Test
public void testuvvCAE() {
testAtomicVirtualization("uvvCAE", null);
}
public static boolean uuvCAS() {
AtomicReference<TestObject> a = new AtomicReference<>(obj6);
return a.compareAndSet(obj7, new TestObject(3));
}
@Test
public void testuuvCAS() {
testAtomicVirtualization("uuvCAS", null, 2);
}
public static Object uuvCAE() {
AtomicReference<TestObject> a = new AtomicReference<>(obj6);
return a.compareAndExchange(obj7, new TestObject(3));
}
@Test
public void testuuvCAE() {
testAtomicVirtualization("uuvCAE", null, 2);
}
public static boolean uuuCAS() {
AtomicReference<TestObject> a = new AtomicReference<>(obj6);
return a.compareAndSet(obj7, obj8);
}
@Test
public void testuuuCAS() {
testAtomicVirtualization("uuuCAS", null);
}
public static Object uuuCAE() {
AtomicReference<TestObject> a = new AtomicReference<>(obj6);
return a.compareAndExchange(obj7, obj8);
}
@Test
public void testuuuCAE() {
testAtomicVirtualization("uuuCAE", null);
}
public static boolean vuvCAS() {
AtomicReference<TestObject> a = new AtomicReference<>(new TestObject(3));
return a.compareAndSet(obj6, new TestObject(4));
}
@Test
public void testvuvCAS() {
testAtomicVirtualization("vuvCAS", JavaConstant.INT_0);
}
public static Object vuvCAE() {
AtomicReference<TestObject> a = new AtomicReference<>(new TestObject(3));
return a.compareAndExchange(obj6, new TestObject(4));
}
@Test
public void testvuvCAE() {
testAtomicVirtualization("vuvCAE", null, 1);
}
public static boolean vuuCAS() {
AtomicReference<TestObject> a = new AtomicReference<>(new TestObject(3));
return a.compareAndSet(obj6, obj7);
}
@Test
public void testvuuCAS() {
testAtomicVirtualization("vuuCAS", JavaConstant.INT_0);
}
public static Object vuuCAE() {
AtomicReference<TestObject> a = new AtomicReference<>(new TestObject(3));
return a.compareAndExchange(obj6, obj7);
}
@Test
public void testvuuCAE() {
testAtomicVirtualization("vuuCAE", null, 1);
}
private void testAtomicVirtualization(String snippet, JavaConstant expectedValue) {
testAtomicVirtualization(snippet, expectedValue, 0);
}
protected void testAtomicVirtualization(String snippet, JavaConstant expectedValue, int expectedAllocations) {
testEscapeAnalysis(snippet, expectedValue, false, expectedAllocations);
test(snippet);
}
}

View File

@ -692,7 +692,7 @@ public class MatchProcessor extends AbstractProcessor {
private RoundEnvironment currentRound;
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
public boolean doProcess(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
if (roundEnv.processingOver()) {
return true;
}

View File

@ -420,9 +420,9 @@ public abstract class SPARCLIRGenerator extends LIRGenerator {
}
@Override
public Variable emitArrayEquals(JavaKind kind, Value array1, Value array2, Value length) {
public Variable emitArrayEquals(JavaKind kind, Value array1, Value array2, Value length, int constantLength, boolean directPointers) {
Variable result = newVariable(LIRKind.value(SPARCKind.WORD));
append(new SPARCArrayEqualsOp(this, kind, result, load(array1), load(array2), asAllocatable(length)));
append(new SPARCArrayEqualsOp(this, kind, result, load(array1), load(array2), asAllocatable(length), directPointers));
return result;
}
@ -477,4 +477,9 @@ public abstract class SPARCLIRGenerator extends LIRGenerator {
public void emitPause() {
append(new SPARCPauseOp());
}
@Override
public void emitSpeculationFence() {
throw GraalError.unimplemented();
}
}

View File

@ -181,6 +181,7 @@ public class CheckGraalInvariants extends GraalCompilerTest {
@Test
@SuppressWarnings("try")
public void test() {
assumeManagementLibraryIsLoadable();
runTest(new InvariantsTool());
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -24,56 +24,74 @@
package org.graalvm.compiler.core.test;
import static org.graalvm.compiler.graph.test.matchers.NodeIterableIsEmpty.isNotEmpty;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
import org.graalvm.compiler.nodes.calc.IntegerLessThanNode;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
import org.graalvm.compiler.phases.tiers.PhaseContext;
import org.junit.Assert;
import org.junit.Test;
public class CompareCanonicalizerTest2 extends GraalCompilerTest {
@SuppressWarnings("unused") private static int sink0;
@SuppressWarnings("unused") private static int sink1;
@SuppressWarnings("unused") private static boolean sink;
private StructuredGraph getCanonicalizedGraph(String name) {
StructuredGraph graph = parseEager(name, AllowAssumptions.YES);
StructuredGraph graph = getRegularGraph(name);
new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
return graph;
}
public void testIntegerTestCanonicalization(String name) {
StructuredGraph graph = getCanonicalizedGraph(name);
Assert.assertThat(graph.getNodes().filter(IntegerLessThanNode.class), isNotEmpty());
private StructuredGraph getRegularGraph(String name) {
StructuredGraph graph = parseEager(name, AllowAssumptions.YES);
return graph;
}
@Test
public void test0() {
testIntegerTestCanonicalization("integerTestCanonicalization0");
assertEquals(getCanonicalizedGraph("integerTestCanonicalization0"), getRegularGraph("integerTestCanonicalization0"));
}
public static void integerTestCanonicalization0(int a) {
sink = 1 < a + 1;
}
@Test
public void test1() {
testIntegerTestCanonicalization("integerTestCanonicalization1");
}
public static void integerTestCanonicalization0(int a) {
if (1 < a + 1) {
sink1 = 0;
} else {
sink0 = -1;
}
assertEquals(getCanonicalizedGraph("integerTestCanonicalization1"), getRegularGraph("integerTestCanonicalization1"));
}
public static void integerTestCanonicalization1(int a) {
if (a - 1 < -1) {
sink1 = 0;
} else {
sink0 = -1;
}
sink = a - 1 < -1;
}
@Test
public void test2() {
assertEquals(getCanonicalizedGraph("integerTestCanonicalization2a"), getCanonicalizedGraph("integerTestCanonicalization2Reference"));
assertEquals(getCanonicalizedGraph("integerTestCanonicalization2b"), getCanonicalizedGraph("integerTestCanonicalization2Reference"));
}
public static boolean integerTestCanonicalization2a(Object[] arr) {
return arr.length - 1 < 0;
}
public static boolean integerTestCanonicalization2b(Object[] arr) {
return arr.length < 1;
}
public static boolean integerTestCanonicalization2Reference(Object[] arr) {
return arr.length == 0;
}
@Test
public void test3() {
assertEquals(getCanonicalizedGraph("integerTestCanonicalization3"), getCanonicalizedGraph("integerTestCanonicalization3Reference"));
}
public static boolean integerTestCanonicalization3(Object[] arr) {
return ((long) (arr.length - 1)) - 1 < 0;
}
public static boolean integerTestCanonicalization3Reference(Object[] arr) {
return arr.length < 2;
}
}

View File

@ -92,16 +92,18 @@ public class CompareCanonicalizerTest3 extends GraalCompilerTest {
assertCanonicallyEqual("integerTestCanonicalization1", "referenceSnippet1");
}
public static void integerTestCanonicalization1(char a) {
if (Integer.compareUnsigned(a - 2, a) < 0) {
public static void integerTestCanonicalization1(char[] a) {
int len = a.length;
if (Integer.compareUnsigned(len - 2, len) < 0) {
sink1 = 0;
} else {
sink0 = -1;
}
}
public static void referenceSnippet1(char a) {
if (Integer.compareUnsigned(a, 2) >= 0) {
public static void referenceSnippet1(char[] a) {
int len = a.length;
if (Integer.compareUnsigned(len, 2) >= 0) {
sink1 = 0;
} else {
sink0 = -1;
@ -238,12 +240,18 @@ public class CompareCanonicalizerTest3 extends GraalCompilerTest {
StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES);
PhaseContext context = new PhaseContext(getProviders());
CanonicalizerPhase canonicalizer = new CanonicalizerPhase();
canonicalizer.apply(graph, context);
new GuardLoweringPhase().apply(graph, new MidTierContext(getProviders(), getTargetProvider(), OptimisticOptimizations.ALL, graph.getProfilingInfo()));
new FrameStateAssignmentPhase().apply(graph);
canonicalizer.apply(graph, context);
StructuredGraph referenceGraph = parseEager(reference, AllowAssumptions.YES);
canonicalizer.apply(referenceGraph, context);
new GuardLoweringPhase().apply(referenceGraph, new MidTierContext(getProviders(), getTargetProvider(), OptimisticOptimizations.ALL, graph.getProfilingInfo()));
new FrameStateAssignmentPhase().apply(referenceGraph);
canonicalizer.apply(referenceGraph, context);
canonicalizer.apply(referenceGraph, context);
assertEquals(referenceGraph, graph, true, true);
}

View File

@ -31,6 +31,7 @@ import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
import org.graalvm.compiler.phases.tiers.PhaseContext;
import org.junit.Ignore;
import org.junit.Test;
import jdk.vm.ci.meta.ResolvedJavaMethod;
@ -282,6 +283,7 @@ public class ConditionalEliminationTest13 extends ConditionalEliminationTestBase
testConditionalElimination("testSnippet9", "referenceSnippet9");
}
@Ignore("Need better unsigned stamps for this conditional elimination to work.")
@Test
public void test10() {
testConditionalElimination("testSnippet10", "referenceSnippet4");

View File

@ -47,6 +47,7 @@ public class DumpPathTest extends GraalCompilerTest {
@Test
public void testDump() throws IOException {
assumeManagementLibraryIsLoadable();
Path dumpDirectoryPath = Files.createTempDirectory("DumpPathTest");
String[] extensions = new String[]{".cfg", ".bgv", ".graph-strings"};
EconomicMap<OptionKey<?>, Object> overrides = OptionValues.newOptionMap();

View File

@ -43,6 +43,7 @@ public class GraphResetDebugTest extends GraalCompilerTest {
@SuppressWarnings("try")
@Test
public void test1() {
assumeManagementLibraryIsLoadable();
EconomicMap<OptionKey<?>, Object> map = EconomicMap.create();
// Configure with an option that enables scopes
map.put(DebugOptions.DumpOnError, true);

View File

@ -34,7 +34,7 @@ import org.graalvm.compiler.nodes.InvokeNode;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.debug.OpaqueNode;
import org.graalvm.compiler.nodes.extended.OpaqueNode;
import org.graalvm.compiler.nodes.extended.LoadHubNode;
import org.graalvm.compiler.nodes.extended.LoadMethodNode;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;

View File

@ -35,7 +35,7 @@ import org.graalvm.compiler.nodes.ReturnNode;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.calc.AddNode;
import org.graalvm.compiler.nodes.debug.OpaqueNode;
import org.graalvm.compiler.nodes.extended.OpaqueNode;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
import org.graalvm.compiler.phases.schedule.SchedulePhase;
@ -71,7 +71,7 @@ public class LongNodeChainTest extends GraalCompilerTest {
addNode.setY(newAddNode);
addNode = newAddNode;
}
opaque.replaceAndDelete(opaque.getValue());
opaque.remove();
} else {
value = constant;
for (int i = 0; i < N; ++i) {

View File

@ -24,6 +24,8 @@
package org.graalvm.compiler.core.test.ea;
import static org.graalvm.compiler.graph.iterators.NodePredicates.isA;
import java.util.List;
import org.graalvm.compiler.core.test.GraalCompilerTest;
@ -33,6 +35,7 @@ import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
import org.graalvm.compiler.nodes.java.NewArrayNode;
import org.graalvm.compiler.nodes.java.NewInstanceNode;
import org.graalvm.compiler.nodes.virtual.AllocatedObjectNode;
import org.graalvm.compiler.nodes.virtual.CommitAllocationNode;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase;
@ -139,6 +142,10 @@ public class EATestBase extends GraalCompilerTest {
* iteration
*/
protected void testEscapeAnalysis(String snippet, JavaConstant expectedConstantResult, boolean iterativeEscapeAnalysis) {
testEscapeAnalysis(snippet, expectedConstantResult, iterativeEscapeAnalysis, 0);
}
protected void testEscapeAnalysis(String snippet, JavaConstant expectedConstantResult, boolean iterativeEscapeAnalysis, int expectedAllocationCount) {
prepareGraph(snippet, iterativeEscapeAnalysis);
if (expectedConstantResult != null) {
for (ReturnNode returnNode : returnNodes) {
@ -146,9 +153,11 @@ public class EATestBase extends GraalCompilerTest {
Assert.assertEquals(expectedConstantResult, returnNode.result().asConstant());
}
}
int newInstanceCount = graph.getNodes().filter(NewInstanceNode.class).count() + graph.getNodes().filter(NewArrayNode.class).count() +
graph.getNodes().filter(CommitAllocationNode.class).count();
Assert.assertEquals(0, newInstanceCount);
int newInstanceCount = graph.getNodes().filter(isA(NewInstanceNode.class).or(NewArrayNode.class).or(AllocatedObjectNode.class)).count();
Assert.assertEquals("Expected allocation count does not match", expectedAllocationCount, newInstanceCount);
if (expectedAllocationCount == 0) {
Assert.assertTrue("Unexpected CommitAllocationNode", graph.getNodes().filter(CommitAllocationNode.class).isEmpty());
}
}
@SuppressWarnings("try")

View File

@ -45,7 +45,7 @@ public class PEAAssertionsTest extends GraalCompilerTest {
public static Object field;
@SuppressWarnings("deprecation")
@SuppressWarnings({"deprecation", "unused"})
public static void snippet1(int i) {
Integer object = new Integer(i);
GraalDirectives.ensureVirtualized(object);
@ -56,7 +56,7 @@ public class PEAAssertionsTest extends GraalCompilerTest {
test("snippet1", 1);
}
@SuppressWarnings("deprecation")
@SuppressWarnings({"deprecation", "unused"})
public static void snippet2(int i) {
Integer object = new Integer(i);
GraalDirectives.ensureVirtualized(object);
@ -68,7 +68,7 @@ public class PEAAssertionsTest extends GraalCompilerTest {
test("snippet2", 1);
}
@SuppressWarnings("deprecation")
@SuppressWarnings({"deprecation", "unused"})
public static void snippet3(int i) {
Integer object = new Integer(i);
field = object;
@ -80,7 +80,7 @@ public class PEAAssertionsTest extends GraalCompilerTest {
test("snippet3", 1);
}
@SuppressWarnings("deprecation")
@SuppressWarnings({"deprecation", "unused"})
public static void snippetHere1(int i) {
Integer object = new Integer(i);
GraalDirectives.ensureVirtualizedHere(object);
@ -91,7 +91,7 @@ public class PEAAssertionsTest extends GraalCompilerTest {
test("snippetHere1", 1);
}
@SuppressWarnings("deprecation")
@SuppressWarnings({"deprecation", "unused"})
public static void snippetHere2(int i) {
Integer object = new Integer(i);
GraalDirectives.ensureVirtualizedHere(object);
@ -103,7 +103,7 @@ public class PEAAssertionsTest extends GraalCompilerTest {
test("snippetHere2", 1);
}
@SuppressWarnings("deprecation")
@SuppressWarnings({"deprecation", "unused"})
public static void snippetHere3(int i) {
Integer object = new Integer(i);
field = object;
@ -136,7 +136,7 @@ public class PEAAssertionsTest extends GraalCompilerTest {
test("snippetBoxing2", 1);
}
@SuppressWarnings("deprecation")
@SuppressWarnings({"deprecation", "unused"})
public static void snippetControlFlow1(boolean b, int i) {
Integer object = new Integer(i);
if (b) {
@ -151,7 +151,7 @@ public class PEAAssertionsTest extends GraalCompilerTest {
test("snippetControlFlow1", true, 1);
}
@SuppressWarnings("deprecation")
@SuppressWarnings({"deprecation", "unused"})
public static void snippetControlFlow2(boolean b, int i) {
Integer object = new Integer(i);
if (b) {
@ -168,7 +168,7 @@ public class PEAAssertionsTest extends GraalCompilerTest {
test("snippetControlFlow2", true, 1);
}
@SuppressWarnings("deprecation")
@SuppressWarnings({"deprecation", "unused"})
public static void snippetControlFlow3(boolean b, int i) {
Integer object = new Integer(i);
GraalDirectives.ensureVirtualized(object);
@ -186,7 +186,7 @@ public class PEAAssertionsTest extends GraalCompilerTest {
test("snippetControlFlow3", true, 1);
}
@SuppressWarnings("deprecation")
@SuppressWarnings({"deprecation", "unused"})
public static void snippetControlFlow4(boolean b, int i) {
Integer object = new Integer(i);
if (b) {
@ -202,7 +202,7 @@ public class PEAAssertionsTest extends GraalCompilerTest {
test("snippetControlFlow4", true, 1);
}
@SuppressWarnings("deprecation")
@SuppressWarnings({"deprecation", "unused"})
public static void snippetControlFlow5(boolean b, int i) {
Integer object = new Integer(i);
if (b) {
@ -223,7 +223,7 @@ public class PEAAssertionsTest extends GraalCompilerTest {
Object b;
}
@SuppressWarnings("deprecation")
@SuppressWarnings({"deprecation", "unused"})
public static void snippetIndirect1(boolean b, int i) {
Integer object = new Integer(i);
TestClass t = new TestClass();
@ -242,7 +242,7 @@ public class PEAAssertionsTest extends GraalCompilerTest {
test("snippetIndirect1", true, 1);
}
@SuppressWarnings("deprecation")
@SuppressWarnings({"deprecation", "unused"})
public static void snippetIndirect2(boolean b, int i) {
Integer object = new Integer(i);
TestClass t = new TestClass();

View File

@ -293,14 +293,14 @@ public class PartialEscapeAnalysisTest extends EATestBase {
Assert.assertTrue("partial escape analysis should have removed all NewArrayNode allocations", graph.getNodes().filter(NewArrayNode.class).isEmpty());
ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, false, false);
double probabilitySum = 0;
double frequencySum = 0;
int materializeCount = 0;
for (CommitAllocationNode materialize : graph.getNodes().filter(CommitAllocationNode.class)) {
probabilitySum += cfg.blockFor(materialize).probability() * materialize.getVirtualObjects().size();
frequencySum += cfg.blockFor(materialize).getRelativeFrequency() * materialize.getVirtualObjects().size();
materializeCount += materialize.getVirtualObjects().size();
}
Assert.assertEquals("unexpected number of MaterializeObjectNodes", expectedCount, materializeCount);
Assert.assertEquals("unexpected probability of MaterializeObjectNodes", expectedProbability, probabilitySum, 0.01);
Assert.assertEquals("unexpected frequency of MaterializeObjectNodes", expectedProbability, frequencySum, 0.01);
for (Node node : graph.getNodes()) {
for (Class<? extends Node> clazz : invalidNodeClasses) {
Assert.assertFalse("instance of invalid class: " + clazz.getSimpleName(), clazz.isInstance(node) && node.usages().isNotEmpty());

View File

@ -0,0 +1,143 @@
/*
* Copyright (c) 2018, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.graalvm.compiler.core.test.ea;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.AtomicReferenceArray;
import org.graalvm.compiler.nodes.java.LogicCompareAndSwapNode;
import org.junit.Test;
import jdk.vm.ci.meta.JavaConstant;
public class UnsafeCompareAndSwapVirtualizationTest extends EATestBase {
private static Object obj1 = new Object();
private static Object obj2 = new Object();
private static final Object OBJ1 = new Object();
public static boolean bothVirtualNoMatch() {
AtomicReference<Object> a = new AtomicReference<>();
return a.compareAndSet(new Object(), new Object());
}
@Test
public void bothVirtualNoMatchTest() {
testEscapeAnalysis("bothVirtualNoMatch", JavaConstant.INT_0, true);
assertTrue(graph.getNodes(LogicCompareAndSwapNode.TYPE).isEmpty());
}
public static boolean bothVirtualMatch() {
Object expect = new Object();
AtomicReference<Object> a = new AtomicReference<>(expect);
return a.compareAndSet(expect, new Object());
}
@Test
public void bothVirtualMatchTest() {
testEscapeAnalysis("bothVirtualMatch", JavaConstant.INT_1, true);
assertTrue(graph.getNodes(LogicCompareAndSwapNode.TYPE).isEmpty());
}
public static boolean expectedVirtualMatch() {
Object o = new Object();
AtomicReference<Object> a = new AtomicReference<>(o);
return a.compareAndSet(o, obj1);
}
@Test
public void expectedVirtualMatchTest() {
testEscapeAnalysis("expectedVirtualMatch", JavaConstant.INT_1, true);
assertTrue(graph.getNodes(LogicCompareAndSwapNode.TYPE).isEmpty());
}
public static boolean expectedVirtualNoMatch() {
Object o = new Object();
AtomicReference<Object> a = new AtomicReference<>();
return a.compareAndSet(o, obj1);
}
@Test
public void expectedVirtualNoMatchTest() {
testEscapeAnalysis("expectedVirtualNoMatch", JavaConstant.INT_0, true);
assertTrue(graph.getNodes(LogicCompareAndSwapNode.TYPE).isEmpty());
}
public static boolean bothNonVirtualNoMatch() {
AtomicReference<Object> a = new AtomicReference<>();
return a.compareAndSet(OBJ1, obj2);
}
@Test
public void bothNonVirtualNoMatchTest() {
testEscapeAnalysis("bothNonVirtualNoMatch", JavaConstant.INT_0, true);
assertTrue(graph.getNodes(LogicCompareAndSwapNode.TYPE).isEmpty());
}
public static boolean bothNonVirtualMatch() {
AtomicReference<Object> a = new AtomicReference<>(OBJ1);
return a.compareAndSet(OBJ1, obj2);
}
@Test
public void bothNonVirtualMatchTest() {
testEscapeAnalysis("bothNonVirtualMatch", JavaConstant.INT_1, true);
assertTrue(graph.getNodes(LogicCompareAndSwapNode.TYPE).isEmpty());
}
public static boolean onlyInitialValueVirtualNoMatch() {
AtomicReference<Object> a = new AtomicReference<>(new Object());
return a.compareAndSet(obj1, obj2);
}
@Test
public void onlyInitialValueVirtualNoMatchTest() {
testEscapeAnalysis("onlyInitialValueVirtualNoMatch", JavaConstant.INT_0, true);
assertTrue(graph.getNodes(LogicCompareAndSwapNode.TYPE).isEmpty());
}
public static boolean onlyInitialValueVirtualMatch() {
Object o = new Object();
AtomicReference<Object> a = new AtomicReference<>(o);
return a.compareAndSet(o, obj2);
}
@Test
public void onlyInitialValueVirtualMatchTest() {
testEscapeAnalysis("onlyInitialValueVirtualMatch", JavaConstant.INT_1, true);
assertTrue(graph.getNodes(LogicCompareAndSwapNode.TYPE).isEmpty());
}
public static boolean bothVirtualNoMatchArray() {
AtomicReferenceArray<Object> array = new AtomicReferenceArray<>(1);
return array.compareAndSet(0, new Object(), new Object());
}
@Test
public void bothVirtualNoMatchArrayTest() {
testEscapeAnalysis("bothVirtualNoMatchArray", JavaConstant.INT_0, true);
assertTrue(graph.getNodes(LogicCompareAndSwapNode.TYPE).isEmpty());
}
}

View File

@ -48,6 +48,8 @@ import org.graalvm.compiler.phases.common.inlining.InliningPhase;
import org.graalvm.compiler.phases.tiers.HighTierContext;
import org.graalvm.compiler.test.SubprocessUtil;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
@ -55,6 +57,11 @@ import java.util.List;
public class PolymorphicInliningTest extends GraalCompilerTest {
@Before
public void checkJavaAgent() {
Assume.assumeFalse("Java Agent found -> skipping", SubprocessUtil.isJavaAgentAttached());
}
@Test
public void testInSubprocess() throws InterruptedException, IOException {
String recursionPropName = getClass().getName() + ".recursion";

View File

@ -120,7 +120,7 @@ public class StaticAnalysisTests {
assertEquals(m(sa, B.class, "foo").getFormalReturn(), t(Data.class));
}
@SuppressWarnings("deprecation")
@SuppressWarnings({"deprecation", "unused"})
static void test03Entry() {
Data data = new Data();
data.f = new Integer(42);
@ -148,7 +148,7 @@ public class StaticAnalysisTests {
assertEquals(m(sa, B.class, "foo").getFormalReturn(), t(Data.class), t(Integer.class));
}
@SuppressWarnings("deprecation")
@SuppressWarnings({"deprecation", "unused"})
static void test04Entry() {
Data data = null;
for (int i = 0; i < 2; i++) {

View File

@ -41,7 +41,6 @@ import java.io.IOException;
import java.io.PrintStream;
import java.util.Map;
import org.graalvm.compiler.debug.DebugCloseable;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.debug.DiagnosticsOutputDirectory;
import org.graalvm.compiler.debug.PathUtilities;
@ -163,8 +162,9 @@ public abstract class CompilationWrapper<T> {
* Creates the {@link DebugContext} to use when retrying a compilation.
*
* @param options the options for configuring the debug context
* @param logStream the log stream to use in the debug context
*/
protected abstract DebugContext createRetryDebugContext(OptionValues options);
protected abstract DebugContext createRetryDebugContext(OptionValues options, PrintStream logStream);
@SuppressWarnings("try")
public final T run(DebugContext initialDebug) {
@ -227,22 +227,27 @@ public abstract class CompilationWrapper<T> {
return handleException(cause);
}
String dir = this.outputDirectory.getPath();
if (dir == null) {
return handleException(cause);
}
String dumpName = PathUtilities.sanitizeFileName(toString());
File dumpPath = new File(dir, dumpName);
dumpPath.mkdirs();
if (!dumpPath.exists()) {
TTY.println("Warning: could not create diagnostics directory " + dumpPath);
return handleException(cause);
File dumpPath = null;
try {
String dir = this.outputDirectory.getPath();
if (dir != null) {
String dumpName = PathUtilities.sanitizeFileName(toString());
dumpPath = new File(dir, dumpName);
dumpPath.mkdirs();
if (!dumpPath.exists()) {
TTY.println("Warning: could not create diagnostics directory " + dumpPath);
dumpPath = null;
}
}
} catch (Throwable t) {
TTY.println("Warning: could not create Graal diagnostic directory");
t.printStackTrace(TTY.out);
}
String message;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try (PrintStream ps = new PrintStream(baos)) {
ps.printf("%s: Compilation of %s failed: ", Thread.currentThread(), this);
ps.printf("%s: Compilation of %s failed:%n", Thread.currentThread(), this);
cause.printStackTrace(ps);
ps.printf("To disable compilation %s notifications, set %s to %s (e.g., -Dgraal.%s=%s).%n",
causeType,
@ -253,11 +258,19 @@ public abstract class CompilationWrapper<T> {
causeType,
actionKey.getName(), ExceptionAction.Print,
actionKey.getName(), ExceptionAction.Print);
ps.println("Retrying compilation of " + this);
if (dumpPath != null) {
ps.println("Retrying compilation of " + this);
} else {
ps.println("Not retrying compilation of " + this + " as the dump path could not be created.");
}
message = baos.toString();
}
TTY.print(message);
if (dumpPath == null) {
return handleException(cause);
}
File retryLogFile = new File(dumpPath, "retry.log");
try (PrintStream ps = new PrintStream(new FileOutputStream(retryLogFile))) {
ps.print(message);
@ -270,15 +283,27 @@ public abstract class CompilationWrapper<T> {
MethodFilter, null,
DumpPath, dumpPath.getPath());
try (DebugContext retryDebug = createRetryDebugContext(retryOptions); DebugCloseable s = retryDebug.disableIntercept()) {
ByteArrayOutputStream logBaos = new ByteArrayOutputStream();
PrintStream ps = new PrintStream(logBaos);
try (DebugContext retryDebug = createRetryDebugContext(retryOptions, ps)) {
T res = performCompilation(retryDebug);
ps.println("There was no exception during retry.");
maybeExitVM(action);
return res;
} catch (Throwable ignore) {
} catch (Throwable e) {
ps.println("Exception during retry:");
e.printStackTrace(ps);
// Failures during retry are silent
T res = handleException(cause);
maybeExitVM(action);
return res;
} finally {
ps.close();
try (FileOutputStream fos = new FileOutputStream(retryLogFile, true)) {
fos.write(logBaos.toByteArray());
} catch (Throwable e) {
TTY.printf("Error writing to %s: %s%n", retryLogFile, e);
}
}
}
}

View File

@ -27,6 +27,8 @@ package org.graalvm.compiler.core.gen;
import static jdk.vm.ci.code.ValueUtil.asRegister;
import static jdk.vm.ci.code.ValueUtil.isLegal;
import static jdk.vm.ci.code.ValueUtil.isRegister;
import static org.graalvm.compiler.core.common.SpeculativeExecutionAttacksMitigations.AllTargets;
import static org.graalvm.compiler.core.common.SpeculativeExecutionAttacksMitigations.Options.MitigateSpeculativeExecutionAttacks;
import static org.graalvm.compiler.core.common.GraalOptions.MatchExpressions;
import static org.graalvm.compiler.debug.DebugOptions.LogVerbose;
import static org.graalvm.compiler.lir.LIR.verifyBlock;
@ -312,6 +314,19 @@ public abstract class NodeLIRBuilder implements NodeLIRBuilderTool, LIRGeneratio
public void doBlockPrologue(@SuppressWarnings("unused") Block block, @SuppressWarnings("unused") OptionValues options) {
if (MitigateSpeculativeExecutionAttacks.getValue(options) == AllTargets) {
boolean hasControlSplitPredecessor = false;
for (Block b : block.getPredecessors()) {
if (b.getSuccessorCount() > 1) {
hasControlSplitPredecessor = true;
break;
}
}
boolean isStartBlock = block.getPredecessorCount() == 0;
if (hasControlSplitPredecessor || isStartBlock) {
getLIRGeneratorTool().emitSpeculationFence();
}
}
}
@Override
@ -372,6 +387,8 @@ public abstract class NodeLIRBuilder implements NodeLIRBuilderTool, LIRGeneratio
debug.log("interior match for %s", valueNode);
} else if (operand instanceof ComplexMatchValue) {
debug.log("complex match for %s", valueNode);
// Set current position to the position of the root matched node.
setSourcePosition(node.getNodeSourcePosition());
ComplexMatchValue match = (ComplexMatchValue) operand;
operand = match.evaluate(this);
if (operand != null) {

View File

@ -47,10 +47,13 @@ import org.graalvm.compiler.nodes.calc.IntegerTestNode;
import org.graalvm.compiler.nodes.calc.LeftShiftNode;
import org.graalvm.compiler.nodes.calc.MulNode;
import org.graalvm.compiler.nodes.calc.NarrowNode;
import org.graalvm.compiler.nodes.calc.NegateNode;
import org.graalvm.compiler.nodes.calc.NotNode;
import org.graalvm.compiler.nodes.calc.ObjectEqualsNode;
import org.graalvm.compiler.nodes.calc.OrNode;
import org.graalvm.compiler.nodes.calc.PointerEqualsNode;
import org.graalvm.compiler.nodes.calc.ReinterpretNode;
import org.graalvm.compiler.nodes.calc.RightShiftNode;
import org.graalvm.compiler.nodes.calc.SignExtendNode;
import org.graalvm.compiler.nodes.calc.SubNode;
import org.graalvm.compiler.nodes.calc.UnsignedRightShiftNode;
@ -78,6 +81,8 @@ import jdk.vm.ci.meta.Value;
@MatchableNode(nodeClass = WriteNode.class, inputs = {"address", "value"})
@MatchableNode(nodeClass = ZeroExtendNode.class, inputs = {"value"})
@MatchableNode(nodeClass = AndNode.class, inputs = {"x", "y"}, commutative = true)
@MatchableNode(nodeClass = NegateNode.class, inputs = {"value"})
@MatchableNode(nodeClass = NotNode.class, inputs = {"value"})
@MatchableNode(nodeClass = FloatEqualsNode.class, inputs = {"x", "y"}, commutative = true)
@MatchableNode(nodeClass = FloatLessThanNode.class, inputs = {"x", "y"}, commutative = true)
@MatchableNode(nodeClass = PointerEqualsNode.class, inputs = {"x", "y"}, commutative = true)
@ -93,6 +98,7 @@ import jdk.vm.ci.meta.Value;
@MatchableNode(nodeClass = PiNode.class, inputs = {"object"})
@MatchableNode(nodeClass = LogicCompareAndSwapNode.class, inputs = {"address", "expectedValue", "newValue"})
@MatchableNode(nodeClass = ValueCompareAndSwapNode.class, inputs = {"address", "expectedValue", "newValue"})
@MatchableNode(nodeClass = RightShiftNode.class, inputs = {"x", "y"})
public abstract class NodeMatchRules {
NodeLIRBuilder lirBuilder;

View File

@ -34,7 +34,7 @@ import org.graalvm.compiler.nodes.LogicConstantNode;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.phases.BasePhase;
import org.graalvm.compiler.phases.PhaseSuite;
import org.graalvm.compiler.phases.common.util.HashSetNodeEventListener;
import org.graalvm.compiler.phases.common.util.EconomicSetNodeEventListener;
import org.graalvm.compiler.phases.tiers.PhaseContext;
/**
@ -68,7 +68,7 @@ public class GraphChangeMonitoringPhase<C extends PhaseContext> extends PhaseSui
* Phase may add nodes but not end up using them so ignore additions. Nodes going dead and
* having their inputs change are the main interesting differences.
*/
HashSetNodeEventListener listener = new HashSetNodeEventListener().exclude(NodeEvent.NODE_ADDED);
EconomicSetNodeEventListener listener = new EconomicSetNodeEventListener().exclude(NodeEvent.NODE_ADDED);
StructuredGraph graphCopy = (StructuredGraph) graph.copy(graph.getDebug());
DebugContext debug = graph.getDebug();
try (NodeEventScope s = graphCopy.trackNodeEvents(listener)) {
@ -90,7 +90,7 @@ public class GraphChangeMonitoringPhase<C extends PhaseContext> extends PhaseSui
}
if (!filteredNodes.isEmpty()) {
/* rerun it on the real graph in a new Debug scope so Dump and Log can find it. */
listener = new HashSetNodeEventListener();
listener = new EconomicSetNodeEventListener();
try (NodeEventScope s = graph.trackNodeEvents(listener)) {
try (DebugContext.Scope s2 = debug.scope("WithGraphChangeMonitoring")) {
if (debug.isDumpEnabled(DebugContext.DETAILED_LEVEL)) {

View File

@ -24,6 +24,9 @@
package org.graalvm.compiler.core.phases;
import static org.graalvm.compiler.core.common.SpeculativeExecutionAttacksMitigations.GuardTargets;
import static org.graalvm.compiler.core.common.SpeculativeExecutionAttacksMitigations.NonDeoptGuardTargets;
import static org.graalvm.compiler.core.common.SpeculativeExecutionAttacksMitigations.Options.MitigateSpeculativeExecutionAttacks;
import static org.graalvm.compiler.core.common.GraalOptions.ConditionalElimination;
import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode;
import static org.graalvm.compiler.core.common.GraalOptions.OptDeoptimizationGrouping;
@ -47,6 +50,7 @@ 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.IncrementalCanonicalizerPhase;
import org.graalvm.compiler.phases.common.InsertGuardFencesPhase;
import org.graalvm.compiler.phases.common.IterativeConditionalEliminationPhase;
import org.graalvm.compiler.phases.common.LockEliminationPhase;
import org.graalvm.compiler.phases.common.LoopSafepointInsertionPhase;
@ -78,6 +82,10 @@ public class MidTier extends PhaseSuite<MidTierContext> {
appendPhase(new GuardLoweringPhase());
if (MitigateSpeculativeExecutionAttacks.getValue(options) == GuardTargets || MitigateSpeculativeExecutionAttacks.getValue(options) == NonDeoptGuardTargets) {
appendPhase(new InsertGuardFencesPhase());
}
if (VerifyHeapAtReturn.getValue(options)) {
appendPhase(new VerifyHeapAtReturnPhase());
}

View File

@ -44,6 +44,7 @@ import org.graalvm.compiler.lir.gen.LIRGenerationResult;
import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.phases.tiers.SuitesProvider;
import org.graalvm.compiler.phases.tiers.TargetProvider;
import org.graalvm.compiler.phases.util.Providers;
@ -153,7 +154,7 @@ public abstract class Backend implements TargetProvider, ValueKindFactory<LIRKin
* Turns a Graal {@link CompilationResult} into a {@link CompiledCode} object that can be passed
* to the VM for code installation.
*/
protected abstract CompiledCode createCompiledCode(ResolvedJavaMethod method, CompilationRequest compilationRequest, CompilationResult compilationResult);
protected abstract CompiledCode createCompiledCode(ResolvedJavaMethod method, CompilationRequest compilationRequest, CompilationResult compilationResult, boolean isDefault, OptionValues options);
/**
* @see #createInstalledCode(DebugContext, ResolvedJavaMethod, CompilationRequest,
@ -192,6 +193,9 @@ public abstract class Backend implements TargetProvider, ValueKindFactory<LIRKin
* @param context a custom debug context to use for the code installation
* @return a reference to the compiled and ready-to-run installed code
* @throws BailoutException if the code installation failed
* @throws IllegalArgumentException if {@code installedCode != null} and this platform does not
* {@linkplain CodeCacheProvider#installCode support} a predefined
* {@link InstalledCode} object
*/
@SuppressWarnings("try")
public InstalledCode createInstalledCode(DebugContext debug, ResolvedJavaMethod method, CompilationRequest compilationRequest, CompilationResult compilationResult,
@ -209,8 +213,8 @@ public abstract class Backend implements TargetProvider, ValueKindFactory<LIRKin
InstalledCode installedCode;
try {
preCodeInstallationTasks(tasks, compilationResult, predefinedInstalledCode);
CompiledCode compiledCode = createCompiledCode(method, compilationRequest, compilationResult);
preCodeInstallationTasks(tasks, compilationResult);
CompiledCode compiledCode = createCompiledCode(method, compilationRequest, compilationResult, isDefault, debug.getOptions());
installedCode = getProviders().getCodeCache().installCode(method, compiledCode, predefinedInstalledCode, speculationLog, isDefault);
assert predefinedInstalledCode == null || installedCode == predefinedInstalledCode;
} catch (Throwable t) {
@ -218,7 +222,7 @@ public abstract class Backend implements TargetProvider, ValueKindFactory<LIRKin
throw t;
}
postCodeInstallationTasks(tasks, installedCode);
postCodeInstallationTasks(tasks, compilationResult, installedCode);
return installedCode;
} catch (Throwable e) {
@ -232,16 +236,16 @@ public abstract class Backend implements TargetProvider, ValueKindFactory<LIRKin
}
}
private static void preCodeInstallationTasks(CodeInstallationTask[] tasks, CompilationResult compilationResult, InstalledCode predefinedInstalledCode) {
private static void preCodeInstallationTasks(CodeInstallationTask[] tasks, CompilationResult compilationResult) {
for (CodeInstallationTask task : tasks) {
task.preProcess(compilationResult, predefinedInstalledCode);
task.preProcess(compilationResult);
}
}
private static void postCodeInstallationTasks(CodeInstallationTask[] tasks, InstalledCode installedCode) {
private static void postCodeInstallationTasks(CodeInstallationTask[] tasks, CompilationResult compilationResult, InstalledCode installedCode) {
try {
for (CodeInstallationTask task : tasks) {
task.postProcess(installedCode);
task.postProcess(compilationResult, installedCode);
}
} catch (Throwable t) {
installedCode.invalidate();
@ -310,19 +314,18 @@ public abstract class Backend implements TargetProvider, ValueKindFactory<LIRKin
* Task to run before code installation.
*
* @param compilationResult the code about to be installed
* @param predefinedInstalledCode a pre-allocated {@link InstalledCode} object that will be
* used as a reference to the installed code. May be {@code null}.
*
*/
public void preProcess(CompilationResult compilationResult, InstalledCode predefinedInstalledCode) {
public void preProcess(CompilationResult compilationResult) {
}
/**
* Task to run after the code is installed.
*
* @param compilationResult the code about to be installed
* @param installedCode a reference to the installed code
*/
public void postProcess(InstalledCode installedCode) {
public void postProcess(CompilationResult compilationResult, InstalledCode installedCode) {
}
/**

View File

@ -197,6 +197,7 @@ public class DebugContextTest {
@Test
public void testEnabledSandbox() {
TimerKeyTest.assumeManagementLibraryIsLoadable();
EconomicMap<OptionKey<?>, Object> map = EconomicMap.create();
// Configure with an option that enables scopes
map.put(DebugOptions.DumpOnError, true);
@ -226,6 +227,7 @@ public class DebugContextTest {
@Test
public void testDisabledSandbox() {
TimerKeyTest.assumeManagementLibraryIsLoadable();
EconomicMap<OptionKey<?>, Object> map = EconomicMap.create();
// Configure with an option that enables scopes
map.put(DebugOptions.DumpOnError, true);
@ -283,6 +285,7 @@ public class DebugContextTest {
@Test
public void testDisableIntercept() {
TimerKeyTest.assumeManagementLibraryIsLoadable();
EconomicMap<OptionKey<?>, Object> map = EconomicMap.create();
// Configure with an option that enables scopes
map.put(DebugOptions.DumpOnError, true);

View File

@ -39,6 +39,7 @@ import org.graalvm.compiler.options.OptionKey;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.serviceprovider.GraalServices;
import org.junit.Assume;
import org.junit.AssumptionViolatedException;
import org.junit.Before;
import org.junit.Test;
@ -47,9 +48,20 @@ public class TimerKeyTest {
@Before
public void checkCapabilities() {
assumeManagementLibraryIsLoadable();
Assume.assumeTrue("skipping management interface test", GraalServices.isCurrentThreadCpuTimeSupported());
}
/** @see <a href="https://bugs.openjdk.java.net/browse/JDK-8076557">JDK-8076557</a> */
static void assumeManagementLibraryIsLoadable() {
try {
/* Trigger loading of the management library using the bootstrap class loader. */
GraalServices.getCurrentThreadAllocatedBytes();
} catch (UnsatisfiedLinkError | NoClassDefFoundError | UnsupportedOperationException e) {
throw new AssumptionViolatedException("Management interface is unavailable: " + e);
}
}
/**
* Actively spins the current thread for at least a given number of milliseconds in such a way
* that timers for the current thread keep ticking over.

View File

@ -80,7 +80,7 @@ import jdk.vm.ci.meta.JavaMethod;
*/
public final class DebugContext implements AutoCloseable {
public static final Description NO_DESCRIPTION = null;
public static final Description NO_DESCRIPTION = new Description(null, "NO_DESCRIPTION");
public static final GlobalMetrics NO_GLOBAL_METRIC_VALUES = null;
public static final Iterable<DebugHandlersFactory> NO_CONFIG_CUSTOMIZERS = Collections.emptyList();
@ -404,6 +404,18 @@ public final class DebugContext implements AutoCloseable {
return new DebugContext(NO_DESCRIPTION, NO_GLOBAL_METRIC_VALUES, DEFAULT_LOG_STREAM, Immutable.create(options), factories);
}
public static DebugContext create(OptionValues options, PrintStream logStream, DebugHandlersFactory factory) {
return new DebugContext(NO_DESCRIPTION, NO_GLOBAL_METRIC_VALUES, logStream, Immutable.create(options), Collections.singletonList(factory));
}
/**
* Creates a {@link DebugContext} based on a given set of option values and {@code factories}.
* The {@link DebugHandlersFactory#LOADER} can be used for the latter.
*/
public static DebugContext create(OptionValues options, Description description, Iterable<DebugHandlersFactory> factories) {
return new DebugContext(description, NO_GLOBAL_METRIC_VALUES, DEFAULT_LOG_STREAM, Immutable.create(options), factories);
}
/**
* Creates a {@link DebugContext}.
*/

View File

@ -127,8 +127,6 @@ public class DebugOptions {
@Option(help = "Enable dumping LIR, register allocation and code generation info to the C1Visualizer.", type = OptionType.Debug)
public static final OptionKey<Boolean> PrintBackendCFG = new OptionKey<>(true);
@Option(help = "Output probabilities for fixed nodes during binary graph dumping.", type = OptionType.Debug)
public static final OptionKey<Boolean> PrintGraphProbabilities = new OptionKey<>(false);
@Option(help = "Enable dumping to the IdealGraphVisualizer.", type = OptionType.Debug)
public static final OptionKey<Boolean> PrintGraph = new OptionKey<>(true);
@Option(help = "Print graphs to files instead of sending them over the network.", type = OptionType.Debug)

View File

@ -86,6 +86,7 @@ public class DiagnosticsOutputDirectory {
}
if (CLOSED.equals(path)) {
TTY.println("Warning: Graal diagnostic directory already closed");
return null;
}
return path;
}
@ -129,6 +130,7 @@ public class DiagnosticsOutputDirectory {
Path dir = Paths.get(outDir);
if (dir.toFile().exists()) {
String prefix = new File(outDir).getName() + "/";
File zip = new File(outDir + ".zip").getAbsoluteFile();
List<Path> toDelete = new ArrayList<>();
try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zip))) {
@ -137,7 +139,7 @@ public class DiagnosticsOutputDirectory {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
if (attrs.isRegularFile()) {
String name = dir.relativize(file).toString();
String name = prefix + dir.relativize(file).toString();
ZipEntry ze = new ZipEntry(name);
zos.putNextEntry(ze);
Files.copy(file, zos);

View File

@ -31,7 +31,7 @@ import org.junit.Assume;
import org.junit.Test;
public class GraphSnippetTest {
@SuppressWarnings("deprecation")
@SuppressWarnings({"deprecation", "unused"})
@Test
public void dumpTheFile() throws Exception {
Class<?> snippets = null;

View File

@ -28,6 +28,7 @@ import static org.graalvm.compiler.graph.NodeSourcePosition.Marker.None;
import static org.graalvm.compiler.graph.NodeSourcePosition.Marker.Placeholder;
import static org.graalvm.compiler.graph.NodeSourcePosition.Marker.Substitution;
import java.util.Iterator;
import java.util.Objects;
import org.graalvm.compiler.bytecode.BytecodeDisassembler;
@ -40,7 +41,7 @@ import jdk.vm.ci.meta.JavaMethod;
import jdk.vm.ci.meta.MetaUtil;
import jdk.vm.ci.meta.ResolvedJavaMethod;
public class NodeSourcePosition extends BytecodePosition {
public class NodeSourcePosition extends BytecodePosition implements Iterable<NodeSourcePosition> {
private static final boolean STRICT_SOURCE_POSITION = Boolean.getBoolean("debug.graal.SourcePositionStrictChecks");
private static final boolean SOURCE_POSITION_BYTECODES = Boolean.getBoolean("debug.graal.SourcePositionDisassemble");
@ -53,17 +54,16 @@ public class NodeSourcePosition extends BytecodePosition {
* Remove marker frames.
*/
public NodeSourcePosition trim() {
if (marker != None) {
return null;
NodeSourcePosition lastMarker = null;
for (NodeSourcePosition current = this; current != null; current = current.getCaller()) {
if (current.marker != None) {
lastMarker = current;
}
}
NodeSourcePosition caller = getCaller();
if (caller != null) {
caller = caller.trim();
if (lastMarker == null) {
return this;
}
if (caller != getCaller()) {
return new NodeSourcePosition(caller, getMethod(), getBCI());
}
return this;
return lastMarker.getCaller();
}
public ResolvedJavaMethod getRootMethod() {
@ -81,6 +81,25 @@ public class NodeSourcePosition extends BytecodePosition {
return true;
}
@Override
public Iterator<NodeSourcePosition> iterator() {
return new Iterator<NodeSourcePosition>() {
private NodeSourcePosition currentPosition = NodeSourcePosition.this;
@Override
public boolean hasNext() {
return currentPosition != null;
}
@Override
public NodeSourcePosition next() {
NodeSourcePosition current = currentPosition;
currentPosition = currentPosition.getCaller();
return current;
}
};
}
enum Marker {
None,
Placeholder,
@ -124,11 +143,19 @@ public class NodeSourcePosition extends BytecodePosition {
}
public static NodeSourcePosition substitution(ResolvedJavaMethod method) {
return substitution(null, method);
return substitution(null, method, BytecodeFrame.INVALID_FRAMESTATE_BCI);
}
public static NodeSourcePosition substitution(ResolvedJavaMethod method, int bci) {
return substitution(null, method, bci);
}
public static NodeSourcePosition substitution(NodeSourcePosition caller, ResolvedJavaMethod method) {
return new NodeSourcePosition(caller, method, BytecodeFrame.INVALID_FRAMESTATE_BCI, Substitution);
return substitution(caller, method, BytecodeFrame.INVALID_FRAMESTATE_BCI);
}
public static NodeSourcePosition substitution(NodeSourcePosition caller, ResolvedJavaMethod method, int bci) {
return new NodeSourcePosition(caller, method, bci, Substitution);
}
public boolean isSubstitution() {
@ -195,10 +222,10 @@ public class NodeSourcePosition extends BytecodePosition {
return new NodeSourcePosition(newSourceLanguagePosition, link, getMethod(), 0);
}
assert link == null || isSubstitution || verifyCaller(this, link) : link;
return new NodeSourcePosition(newSourceLanguagePosition, link, getMethod(), getBCI());
assert !isSubstitution || marker == None;
return new NodeSourcePosition(newSourceLanguagePosition, link, getMethod(), getBCI(), isSubstitution ? Substitution : None);
} else {
return new NodeSourcePosition(getCaller().addCaller(newSourceLanguagePosition, link, isSubstitution), getMethod(), getBCI());
return new NodeSourcePosition(getCaller().addCaller(newSourceLanguagePosition, link, isSubstitution), getMethod(), getBCI(), marker);
}
}
@ -221,6 +248,9 @@ public class NodeSourcePosition extends BytecodePosition {
private static void format(StringBuilder sb, NodeSourcePosition pos) {
MetaUtil.appendLocation(sb.append("at "), pos.getMethod(), pos.getBCI());
if (pos.marker != None) {
sb.append(" " + pos.marker);
}
if (SOURCE_POSITION_BYTECODES) {
String disassembly = BytecodeDisassembler.disassembleOne(pos.getMethod(), pos.getBCI());
if (disassembly != null && disassembly.length() > 0) {

View File

@ -56,7 +56,6 @@ import org.graalvm.compiler.hotspot.meta.HotSpotStampProvider;
import org.graalvm.compiler.hotspot.meta.HotSpotSuitesProvider;
import org.graalvm.compiler.hotspot.word.HotSpotWordTypes;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
import org.graalvm.compiler.nodes.spi.LoweringProvider;
import org.graalvm.compiler.nodes.spi.Replacements;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.phases.Phase;
@ -148,7 +147,7 @@ public class AArch64HotSpotBackendFactory implements HotSpotBackendFactory {
replacements = createReplacements(graalRuntime.getOptions(), p, snippetReflection, bytecodeProvider);
}
try (InitTimer rt = timer("create GraphBuilderPhase plugins")) {
plugins = createGraphBuilderPlugins(compilerConfiguration, config, constantReflection, foreignCalls, lowerer, metaAccess, snippetReflection, replacements, wordTypes, stampProvider);
plugins = createGraphBuilderPlugins(compilerConfiguration, config, constantReflection, foreignCalls, metaAccess, snippetReflection, replacements, wordTypes);
replacements.setGraphBuilderPlugins(plugins);
}
try (InitTimer rt = timer("create Suites provider")) {
@ -164,10 +163,9 @@ public class AArch64HotSpotBackendFactory implements HotSpotBackendFactory {
}
protected Plugins createGraphBuilderPlugins(CompilerConfiguration compilerConfiguration, GraalHotSpotVMConfig config, HotSpotConstantReflectionProvider constantReflection,
HotSpotHostForeignCallsProvider foreignCalls, LoweringProvider lowerer, HotSpotMetaAccessProvider metaAccess, HotSpotSnippetReflectionProvider snippetReflection,
HotSpotReplacementsImpl replacements, HotSpotWordTypes wordTypes, HotSpotStampProvider stampProvider) {
Plugins plugins = HotSpotGraphBuilderPlugins.create(compilerConfiguration, config, wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, lowerer, stampProvider,
replacements);
HotSpotHostForeignCallsProvider foreignCalls, HotSpotMetaAccessProvider metaAccess, HotSpotSnippetReflectionProvider snippetReflection,
HotSpotReplacementsImpl replacements, HotSpotWordTypes wordTypes) {
Plugins plugins = HotSpotGraphBuilderPlugins.create(compilerConfiguration, config, wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, replacements);
AArch64GraphBuilderPlugins.register(plugins, replacements.getDefaultReplacementBytecodeProvider(), false);
return plugins;
}

View File

@ -29,7 +29,7 @@ import static jdk.vm.ci.meta.JavaConstant.INT_0;
import static jdk.vm.ci.meta.JavaConstant.LONG_0;
import org.graalvm.compiler.core.aarch64.AArch64MoveFactory;
import org.graalvm.compiler.lir.LIRInstruction;
import org.graalvm.compiler.lir.aarch64.AArch64LIRInstruction;
import jdk.vm.ci.hotspot.HotSpotCompressedNullConstant;
import jdk.vm.ci.hotspot.HotSpotConstant;
@ -52,7 +52,7 @@ public class AArch64HotSpotMoveFactory extends AArch64MoveFactory {
}
@Override
public LIRInstruction createLoad(AllocatableValue dst, Constant src) {
public AArch64LIRInstruction createLoad(AllocatableValue dst, Constant src) {
Constant usedSource;
if (COMPRESSED_NULL.equals(src)) {
usedSource = INT_0;

View File

@ -0,0 +1,80 @@
/*
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.graalvm.compiler.hotspot.amd64.test;
import org.junit.Test;
import org.junit.Assert;
/**
* Tests Bit Manipulation Instruction andn pattern matching and result.
*/
public class BmiAndn extends BmiCompilerTest {
// from Intel manual VEX.NDS.LZ.0F38.W0 F2 /r, example c4e260f2c2
private final byte[] instrMask = new byte[]{
(byte) 0xFF,
(byte) 0x1F,
(byte) 0x00,
(byte) 0xFF};
private final byte[] instrPattern = new byte[]{
(byte) 0xC4, // prefix for 3-byte VEX instruction
(byte) 0x02, // 00010 implied 0F 38 leading opcode bytes
(byte) 0x00,
(byte) 0xF2};
public int andni(int n1, int n2) {
return (n1 & (~n2));
}
public long andnl(long n1, long n2) {
return (n1 & (~n2));
}
// Pattern matching check for andni
@Test
public void test1() {
Assert.assertTrue(verifyPositive("andni", instrMask, instrPattern));
}
// Pattern matching check for andnl
@Test
public void test2() {
Assert.assertTrue(verifyPositive("andnl", instrMask, instrPattern));
}
// Result correctness check
@Test
public void test3() {
int n1 = 42;
int n2 = 100;
test("andni", n1, n2);
}
@Test
public void test4() {
long n1 = 420000000;
long n2 = 1000000000;
test("andnl", n1, n2);
}
}

View File

@ -0,0 +1,80 @@
/*
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.graalvm.compiler.hotspot.amd64.test;
import org.junit.Test;
import org.junit.Assert;
/**
* Tests Bit Manipulation Instruction blsi pattern matching and result.
*/
public class BmiBlsi extends BmiCompilerTest {
// from Intel manual VEX.NDD.LZ.0F38.W0 F3 /3, example c4e260f2c2
private final byte[] instrMask = new byte[]{
(byte) 0xFF,
(byte) 0x1F,
(byte) 0x00,
(byte) 0xFF,
(byte) 0b0011_1000};
private final byte[] instrPattern = new byte[]{
(byte) 0xC4, // prefix for 3-byte VEX instruction
(byte) 0x02, // 00010 implied 0F 38 leading opcode bytes
(byte) 0x00,
(byte) 0xF3,
(byte) 0b0001_1000}; // bits 543 == 011 (3)
public int blsii(int n1) {
return (n1 & (-n1));
}
public long blsil(long n1) {
return (n1 & (-n1));
}
// Pattern matching check for blsii
@Test
public void test1() {
Assert.assertTrue(verifyPositive("blsii", instrMask, instrPattern));
}
// Pattern matching check for blsil
@Test
public void test2() {
Assert.assertTrue(verifyPositive("blsil", instrMask, instrPattern));
}
// Result correctness check
@Test
public void test3() {
int n1 = 42;
test("blsii", n1);
}
@Test
public void test4() {
long n1 = 420000000;
test("blsil", n1);
}
}

View File

@ -0,0 +1,80 @@
/*
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.graalvm.compiler.hotspot.amd64.test;
import org.junit.Test;
import org.junit.Assert;
/**
* Tests Bit Manipulation Instruction blsmsk pattern matching and result.
*/
public class BmiBlsmsk extends BmiCompilerTest {
// from Intel manual VEX.NDD.LZ.0F38.W0 F3 /2, example c4e260f2c2
private final byte[] instrMask = new byte[]{
(byte) 0xFF,
(byte) 0x1F,
(byte) 0x00,
(byte) 0xFF,
(byte) 0b0011_1000};
private final byte[] instrPattern = new byte[]{
(byte) 0xC4, // prefix for 3-byte VEX instruction
(byte) 0x02, // 00010 implied 0F 38 leading opcode bytes
(byte) 0x00,
(byte) 0xF3,
(byte) 0b0001_0000}; // bits 543 == 010 (2)
public int blsmski(int n1) {
return (n1 ^ (n1 - 1));
}
public long blsmskl(long n1) {
return (n1 ^ (n1 - 1));
}
// Pattern matching check for blsmski
@Test
public void test1() {
Assert.assertTrue(verifyPositive("blsmski", instrMask, instrPattern));
}
// Pattern matching check for blsmskl
@Test
public void test2() {
Assert.assertTrue(verifyPositive("blsmskl", instrMask, instrPattern));
}
// Result correctness check
@Test
public void test3() {
int n1 = 42;
test("blsmski", n1);
}
@Test
public void test4() {
long n1 = 420000000;
test("blsmskl", n1);
}
}

View File

@ -0,0 +1,80 @@
/*
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.graalvm.compiler.hotspot.amd64.test;
import org.junit.Test;
import org.junit.Assert;
/**
* Tests Bit Manipulation Instruction blsr pattern matching and result.
*/
public class BmiBlsr extends BmiCompilerTest {
// from Intel manual VEX.NDD.LZ.0F38.W0 F3 /3, example c4e260f2c2
private final byte[] instrMask = new byte[]{
(byte) 0xFF,
(byte) 0x1F,
(byte) 0x00,
(byte) 0xFF,
(byte) 0b0011_1000};
private final byte[] instrPattern = new byte[]{
(byte) 0xC4, // prefix for 3-byte VEX instruction
(byte) 0x02, // 00010 implied 0F 38 leading opcode bytes
(byte) 0x00,
(byte) 0xF3,
(byte) 0b0000_1000}; // bits 543 == 011 (3)
public int blsri(int n1) {
return (n1 & (n1 - 1));
}
public long blsrl(long n1) {
return (n1 & (n1 - 1));
}
// Pattern matching check for blsri
@Test
public void test1() {
Assert.assertTrue(verifyPositive("blsri", instrMask, instrPattern));
}
// Pattern matching check for blsrl
@Test
public void test2() {
Assert.assertTrue(verifyPositive("blsrl", instrMask, instrPattern));
}
// Result correctness check
@Test
public void test3() {
int n1 = 42;
test("blsri", n1);
}
@Test
public void test4() {
long n1 = 420000000;
test("blsrl", n1);
}
}

View File

@ -0,0 +1,81 @@
/*
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.graalvm.compiler.hotspot.amd64.test;
import static org.junit.Assume.assumeTrue;
import org.graalvm.compiler.api.test.Graal;
import org.graalvm.compiler.code.CompilationResult;
import org.graalvm.compiler.core.test.GraalCompilerTest;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.runtime.RuntimeProvider;
import org.junit.Assert;
import org.junit.Before;
import jdk.vm.ci.amd64.AMD64;
import jdk.vm.ci.code.Architecture;
import jdk.vm.ci.meta.ResolvedJavaMethod;
public abstract class BmiCompilerTest extends GraalCompilerTest {
@Before
public void checkAMD64() {
Architecture arch = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getTarget().arch;
assumeTrue("skipping AMD64 specific test", arch instanceof AMD64);
assumeTrue("skipping BMI1 specific test", ((AMD64) arch).getFeatures().contains(AMD64.CPUFeature.BMI1));
}
public boolean verifyPositive(String methodName, byte[] instrMask, byte[] instrPattern) {
ResolvedJavaMethod method = getResolvedJavaMethod(methodName);
StructuredGraph graph = parseForCompile(method);
CompilationResult c = compile(method, graph);
byte[] targetCode = c.getTargetCode();
return countCpuInstructions(targetCode, instrMask, instrPattern) >= 1;
}
public static int countCpuInstructions(byte[] nativeCode, byte[] instrMask, byte[] instrPattern) {
int count = 0;
int patternSize = Math.min(instrMask.length, instrPattern.length);
boolean found;
Assert.assertTrue(patternSize > 0);
for (int i = 0, n = nativeCode.length - patternSize; i < n;) {
found = true;
for (int j = 0; j < patternSize; j++) {
if ((nativeCode[i + j] & instrMask[j]) != instrPattern[j]) {
found = false;
break;
}
}
if (found) {
++count;
i += patternSize - 1;
}
i++;
}
return count;
}
}

View File

@ -0,0 +1,92 @@
/*
* Copyright (c) 2018, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.graalvm.compiler.hotspot.amd64;
import jdk.vm.ci.meta.JavaKind;
import org.graalvm.compiler.api.replacements.Snippet;
import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage;
import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
import org.graalvm.compiler.hotspot.stubs.SnippetStub;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.replacements.amd64.AMD64ArrayIndexOfNode;
import jdk.internal.vm.compiler.word.Pointer;
public class AMD64ArrayIndexOfStub extends SnippetStub {
public AMD64ArrayIndexOfStub(ForeignCallDescriptor foreignCallDescriptor, OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) {
super(foreignCallDescriptor.getName(), options, providers, linkage);
}
@Snippet
private static int indexOfTwoConsecutiveBytes(Pointer arrayPointer, int arrayLength, int searchValue) {
return AMD64ArrayIndexOfNode.optimizedArrayIndexOf(JavaKind.Byte, true, arrayPointer, arrayLength, searchValue);
}
@Snippet
private static int indexOfTwoConsecutiveChars(Pointer arrayPointer, int arrayLength, int searchValue) {
return AMD64ArrayIndexOfNode.optimizedArrayIndexOf(JavaKind.Char, true, arrayPointer, arrayLength, searchValue);
}
@Snippet
private static int indexOf1Byte(Pointer arrayPointer, int arrayLength, byte b) {
return AMD64ArrayIndexOfNode.optimizedArrayIndexOf(JavaKind.Byte, arrayPointer, arrayLength, b);
}
@Snippet
private static int indexOf2Bytes(Pointer arrayPointer, int arrayLength, byte b1, byte b2) {
return AMD64ArrayIndexOfNode.optimizedArrayIndexOf(JavaKind.Byte, arrayPointer, arrayLength, b1, b2);
}
@Snippet
private static int indexOf3Bytes(Pointer arrayPointer, int arrayLength, byte b1, byte b2, byte b3) {
return AMD64ArrayIndexOfNode.optimizedArrayIndexOf(JavaKind.Byte, arrayPointer, arrayLength, b1, b2, b3);
}
@Snippet
private static int indexOf4Bytes(Pointer arrayPointer, int arrayLength, byte b1, byte b2, byte b3, byte b4) {
return AMD64ArrayIndexOfNode.optimizedArrayIndexOf(JavaKind.Byte, arrayPointer, arrayLength, b1, b2, b3, b4);
}
@Snippet
private static int indexOf1Char(Pointer arrayPointer, int arrayLength, char c) {
return AMD64ArrayIndexOfNode.optimizedArrayIndexOf(JavaKind.Char, arrayPointer, arrayLength, c);
}
@Snippet
private static int indexOf2Chars(Pointer arrayPointer, int arrayLength, char c1, char c2) {
return AMD64ArrayIndexOfNode.optimizedArrayIndexOf(JavaKind.Char, arrayPointer, arrayLength, c1, c2);
}
@Snippet
private static int indexOf3Chars(Pointer arrayPointer, int arrayLength, char c1, char c2, char c3) {
return AMD64ArrayIndexOfNode.optimizedArrayIndexOf(JavaKind.Char, arrayPointer, arrayLength, c1, c2, c3);
}
@Snippet
private static int indexOf4Chars(Pointer arrayPointer, int arrayLength, char c1, char c2, char c3, char c4) {
return AMD64ArrayIndexOfNode.optimizedArrayIndexOf(JavaKind.Char, arrayPointer, arrayLength, c1, c2, c3, c4);
}
}

View File

@ -52,7 +52,6 @@ import org.graalvm.compiler.hotspot.meta.HotSpotStampProvider;
import org.graalvm.compiler.hotspot.meta.HotSpotSuitesProvider;
import org.graalvm.compiler.hotspot.word.HotSpotWordTypes;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
import org.graalvm.compiler.nodes.spi.LoweringProvider;
import org.graalvm.compiler.nodes.spi.Replacements;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.phases.common.AddressLoweringPhase;
@ -142,8 +141,7 @@ public class AMD64HotSpotBackendFactory implements HotSpotBackendFactory {
replacements = createReplacements(options, p, snippetReflection, bytecodeProvider);
}
try (InitTimer rt = timer("create GraphBuilderPhase plugins")) {
plugins = createGraphBuilderPlugins(compilerConfiguration, config, options, target, constantReflection, foreignCalls, lowerer, metaAccess, snippetReflection, replacements, wordTypes,
stampProvider);
plugins = createGraphBuilderPlugins(compilerConfiguration, config, options, target, constantReflection, foreignCalls, metaAccess, snippetReflection, replacements, wordTypes);
replacements.setGraphBuilderPlugins(plugins);
}
try (InitTimer rt = timer("create Suites provider")) {
@ -159,10 +157,9 @@ public class AMD64HotSpotBackendFactory implements HotSpotBackendFactory {
}
protected Plugins createGraphBuilderPlugins(CompilerConfiguration compilerConfiguration, GraalHotSpotVMConfig config, OptionValues options, TargetDescription target,
HotSpotConstantReflectionProvider constantReflection, HotSpotHostForeignCallsProvider foreignCalls, LoweringProvider lowerer, HotSpotMetaAccessProvider metaAccess,
HotSpotSnippetReflectionProvider snippetReflection, HotSpotReplacementsImpl replacements, HotSpotWordTypes wordTypes, HotSpotStampProvider stampProvider) {
Plugins plugins = HotSpotGraphBuilderPlugins.create(compilerConfiguration, config, wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, lowerer, stampProvider,
replacements);
HotSpotConstantReflectionProvider constantReflection, HotSpotHostForeignCallsProvider foreignCalls, HotSpotMetaAccessProvider metaAccess,
HotSpotSnippetReflectionProvider snippetReflection, HotSpotReplacementsImpl replacements, HotSpotWordTypes wordTypes) {
Plugins plugins = HotSpotGraphBuilderPlugins.create(compilerConfiguration, config, wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, replacements);
AMD64GraphBuilderPlugins.register(plugins, replacements.getDefaultReplacementBytecodeProvider(), (AMD64) target.arch, GraalArithmeticStubs.getValue(options), false);
return plugins;
}

Some files were not shown because too many files have changed in this diff Show More