8210777: Update Graal
Reviewed-by: kvn
This commit is contained in:
parent
c8ebf4da3b
commit
971575362a
@ -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 \
|
||||
|
@ -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 \
|
||||
|
@ -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);
|
||||
|
@ -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() {
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
/**
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
|
@ -22,6 +22,22 @@
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
package jdk.internal.vm.compiler.word.impl;
|
||||
|
||||
import jdk.internal.vm.compiler.word.WordBase;
|
||||
|
@ -22,6 +22,22 @@
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
package jdk.internal.vm.compiler.word.impl;
|
||||
|
||||
/**
|
||||
|
@ -22,6 +22,22 @@
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
package jdk.internal.vm.compiler.word.impl;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
|
@ -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;
|
@ -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;
|
||||
|
||||
|
@ -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()}.
|
||||
*/
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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:
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
@ -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)) {
|
||||
|
@ -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;
|
||||
|
@ -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));
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -41,6 +41,4 @@ public interface CodeGenProviders {
|
||||
ForeignCallsProvider getForeignCalls();
|
||||
|
||||
ConstantReflectionProvider getConstantReflection();
|
||||
|
||||
ArrayOffsetProvider getArrayOffsetProvider();
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -181,6 +181,7 @@ public class CheckGraalInvariants extends GraalCompilerTest {
|
||||
@Test
|
||||
@SuppressWarnings("try")
|
||||
public void test() {
|
||||
assumeManagementLibraryIsLoadable();
|
||||
runTest(new InvariantsTool());
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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");
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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")
|
||||
|
@ -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();
|
||||
|
@ -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());
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
@ -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";
|
||||
|
@ -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++) {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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)) {
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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) {
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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}.
|
||||
*/
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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
Loading…
Reference in New Issue
Block a user