8210777: Update Graal

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -22,6 +22,22 @@
*/ */
package jdk.internal.vm.compiler.collections.test; package jdk.internal.vm.compiler.collections.test;
import java.util.Arrays; import java.util.Arrays;
@ -117,7 +133,7 @@ public class EconomicMapImplTest {
Assert.assertTrue(set.add(newInteger(0))); Assert.assertTrue(set.add(newInteger(0)));
} }
@SuppressWarnings("deprecation") @SuppressWarnings({"deprecation", "unused"})
private static Integer newInteger(int value) { private static Integer newInteger(int value) {
return new Integer(value); return new Integer(value);
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -22,6 +22,22 @@
*/ */
package jdk.internal.vm.compiler.collections.test; package jdk.internal.vm.compiler.collections.test;
import java.util.Arrays; import java.util.Arrays;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -22,6 +22,22 @@
*/ */
package jdk.internal.vm.compiler.collections.test; package jdk.internal.vm.compiler.collections.test;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -22,6 +22,22 @@
*/ */
package jdk.internal.vm.compiler.collections.test; package jdk.internal.vm.compiler.collections.test;
import java.util.ArrayList; import java.util.ArrayList;
@ -145,7 +161,7 @@ public class EconomicSetTest {
Assert.assertEquals(newInteger(9), finalList.get(0)); Assert.assertEquals(newInteger(9), finalList.get(0));
} }
@SuppressWarnings("deprecation") @SuppressWarnings({"deprecation", "unused"})
private static Integer newInteger(int value) { private static Integer newInteger(int value) {
return new Integer(value); return new Integer(value);
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -22,6 +22,22 @@
*/ */
package jdk.internal.vm.compiler.collections.test; package jdk.internal.vm.compiler.collections.test;
import jdk.internal.vm.compiler.collections.Equivalence; import jdk.internal.vm.compiler.collections.Equivalence;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -22,6 +22,22 @@
*/ */
package jdk.internal.vm.compiler.collections.test; package jdk.internal.vm.compiler.collections.test;
import jdk.internal.vm.compiler.collections.Pair; import jdk.internal.vm.compiler.collections.Pair;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -22,6 +22,22 @@
*/ */
package jdk.internal.vm.compiler.collections; package jdk.internal.vm.compiler.collections;
import java.util.Iterator; import java.util.Iterator;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -22,6 +22,22 @@
*/ */
package jdk.internal.vm.compiler.collections; package jdk.internal.vm.compiler.collections;
import java.util.Iterator; import java.util.Iterator;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -22,6 +22,22 @@
*/ */
package jdk.internal.vm.compiler.collections; package jdk.internal.vm.compiler.collections;
import java.util.Iterator; import java.util.Iterator;

View File

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

View File

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

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -22,6 +22,22 @@
*/ */
package jdk.internal.vm.compiler.collections; package jdk.internal.vm.compiler.collections;
import java.util.Objects; import java.util.Objects;

View File

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

View File

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

View File

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

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -35,4 +35,20 @@
*/ */
package jdk.internal.vm.compiler.collections; package jdk.internal.vm.compiler.collections;

View File

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

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -22,6 +22,22 @@
*/ */
package jdk.internal.vm.compiler.word; package jdk.internal.vm.compiler.word;
// JaCoCo Exclude // JaCoCo Exclude

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -22,6 +22,22 @@
*/ */
package jdk.internal.vm.compiler.word; package jdk.internal.vm.compiler.word;
/** /**
@ -959,7 +975,8 @@ public interface Pointer extends UnsignedWord, PointerBase {
void writeObject(WordBase offset, Object val); 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. * offset are in bytes.
* <p> * <p>
* The offset is always treated as a {@link SignedWord} value. However, the static type is * 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). * knows that the highest-order bit of the unsigned value is never used).
* *
* @param offset the signed offset for the memory access * @param offset the signed offset for the memory access
* @param expectedValue the expected value of the atomic exchange * @param expectedValue the expected current value at the memory address
* @param newValue the new value of the atomic exchange * @param newValue the new value for the atomic exchange
* @param locationIdentity the identity of the memory location * @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 * @since 1.0
*/ */
int compareAndSwapInt(WordBase offset, int expectedValue, int newValue, LocationIdentity locationIdentity); 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. * offset are in bytes.
* <p> * <p>
* The offset is always treated as a {@link SignedWord} value. However, the static type is * 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). * knows that the highest-order bit of the unsigned value is never used).
* *
* @param offset the signed offset for the memory access * @param offset the signed offset for the memory access
* @param expectedValue the expected value of the atomic exchange * @param expectedValue the expected current value at the memory address
* @param newValue the new value of the atomic exchange * @param newValue the new value for the atomic exchange
* @param locationIdentity the identity of the memory location * @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 * @since 1.0
*/ */
long compareAndSwapLong(WordBase offset, long expectedValue, long newValue, LocationIdentity locationIdentity); 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. * offset are in bytes.
* <p> * <p>
* The offset is always treated as a {@link SignedWord} value. However, the static type is * 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). * knows that the highest-order bit of the unsigned value is never used).
* *
* @param offset the signed offset for the memory access * @param offset the signed offset for the memory access
* @param expectedValue the expected value of the atomic exchange * @param expectedValue the expected current value at the memory address
* @param newValue the new value of the atomic exchange * @param newValue the new value for the atomic exchange
* @param locationIdentity the identity of the memory location * @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 * @since 1.0
*/ */
<T extends WordBase> T compareAndSwapWord(WordBase offset, T expectedValue, T newValue, LocationIdentity locationIdentity); <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. * offset are in bytes.
* <p> * <p>
* The offset is always treated as a {@link SignedWord} value. However, the static type is * 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). * knows that the highest-order bit of the unsigned value is never used).
* *
* @param offset the signed offset for the memory access * @param offset the signed offset for the memory access
* @param expectedValue the expected value of the atomic exchange * @param expectedValue the expected current value at the memory address
* @param newValue the new value of the atomic exchange * @param newValue the new value for the atomic exchange
* @param locationIdentity the identity of the memory location * @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 * @since 1.0
*/ */
Object compareAndSwapObject(WordBase offset, Object expectedValue, Object newValue, LocationIdentity locationIdentity); 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. * offset are in bytes.
* <p> * <p>
* The offset is always treated as a {@link SignedWord} value. However, the static type is * 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). * knows that the highest-order bit of the unsigned value is never used).
* *
* @param offset the signed offset for the memory access * @param offset the signed offset for the memory access
* @param expectedValue the expected value of the atomic exchange * @param expectedValue the expected current value at the memory address
* @param newValue the new value of the atomic exchange * @param newValue the new value for the atomic exchange
* @param locationIdentity the identity of the memory location * @param locationIdentity the identity of the memory location
* @return {@code true} if successful. False return indicates that the actual value was not * @return {@code true} if successful. False return indicates that the actual value was not
* equal to the expected value. * 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); 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. * offset are in bytes.
* <p> * <p>
* The offset is always treated as a {@link SignedWord} value. However, the static type is * 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). * knows that the highest-order bit of the unsigned value is never used).
* *
* @param offset the signed offset for the memory access * @param offset the signed offset for the memory access
* @param expectedValue the expected value of the atomic exchange * @param expectedValue the expected current value at the memory address
* @param newValue the new value of the atomic exchange * @param newValue the new value for the atomic exchange
* @param locationIdentity the identity of the memory location * @param locationIdentity the identity of the memory location
* @return {@code true} if successful. False return indicates that the actual value was not * @return {@code true} if successful. False return indicates that the actual value was not
* equal to the expected value. * 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); 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. * offset are in bytes.
* <p> * <p>
* The offset is always treated as a {@link SignedWord} value. However, the static type is * 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). * knows that the highest-order bit of the unsigned value is never used).
* *
* @param offset the signed offset for the memory access * @param offset the signed offset for the memory access
* @param expectedValue the expected value of the atomic exchange * @param expectedValue the expected current value at the memory address
* @param newValue the new value of the atomic exchange * @param newValue the new value for the atomic exchange
* @param locationIdentity the identity of the memory location * @param locationIdentity the identity of the memory location
* @return {@code true} if successful. False return indicates that the actual value was not * @return {@code true} if successful. False return indicates that the actual value was not
* equal to the expected value. * 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); 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. * offset are in bytes.
* <p> * <p>
* The offset is always treated as a {@link SignedWord} value. However, the static type is * 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). * knows that the highest-order bit of the unsigned value is never used).
* *
* @param offset the signed offset for the memory access * @param offset the signed offset for the memory access
* @param expectedValue the expected value of the atomic exchange * @param expectedValue the expected current value at the memory address
* @param newValue the new value of the atomic exchange * @param newValue the new value for the atomic exchange
* @param locationIdentity the identity of the memory location * @param locationIdentity the identity of the memory location
* @return {@code true} if successful. False return indicates that the actual value was not * @return {@code true} if successful. False return indicates that the actual value was not
* equal to the expected value. * equal to the expected value.
@ -1206,68 +1234,77 @@ public interface Pointer extends UnsignedWord, PointerBase {
void writeObject(int offset, Object val); 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. * offset are in bytes.
* *
* @param offset the signed offset for the memory access * @param offset the signed offset for the memory access
* @param expectedValue the expected value of the atomic exchange * @param expectedValue the expected current value at the memory address
* @param newValue the new value of the atomic exchange * @param newValue the new value for the atomic exchange
* @param locationIdentity the identity of the memory location * @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 * @since 1.0
*/ */
int compareAndSwapInt(int offset, int expectedValue, int newValue, LocationIdentity locationIdentity); 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. * offset are in bytes.
* *
* @param offset the signed offset for the memory access * @param offset the signed offset for the memory access
* @param expectedValue the expected value of the atomic exchange * @param expectedValue the expected current value at the memory address
* @param newValue the new value of the atomic exchange * @param newValue the new value for the atomic exchange
* @param locationIdentity the identity of the memory location * @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 * @since 1.0
*/ */
long compareAndSwapLong(int offset, long expectedValue, long newValue, LocationIdentity locationIdentity); 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. * offset are in bytes.
* *
* @param offset the signed offset for the memory access * @param offset the signed offset for the memory access
* @param expectedValue the expected value of the atomic exchange * @param expectedValue the expected current value at the memory address
* @param newValue the new value of the atomic exchange * @param newValue the new value for the atomic exchange
* @param locationIdentity the identity of the memory location * @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 * @since 1.0
*/ */
<T extends WordBase> T compareAndSwapWord(int offset, T expectedValue, T newValue, LocationIdentity locationIdentity); <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. * offset are in bytes.
* *
* @param offset the signed offset for the memory access * @param offset the signed offset for the memory access
* @param expectedValue the expected value of the atomic exchange * @param expectedValue the expected current value at the memory address
* @param newValue the new value of the atomic exchange * @param newValue the new value for the atomic exchange
* @param locationIdentity the identity of the memory location * @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 * @since 1.0
*/ */
Object compareAndSwapObject(int offset, Object expectedValue, Object newValue, LocationIdentity locationIdentity); 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. * offset are in bytes.
* *
* @param offset the signed offset for the memory access * @param offset the signed offset for the memory access
* @param expectedValue the expected value of the atomic exchange * @param expectedValue the expected current value at the memory address
* @param newValue the new value of the atomic exchange * @param newValue the new value for the atomic exchange
* @param locationIdentity the identity of the memory location * @param locationIdentity the identity of the memory location
* @return {@code true} if successful. False return indicates that the actual value was not * @return {@code true} if successful. False return indicates that the actual value was not
* equal to the expected value. * 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); 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. * offset are in bytes.
* *
* @param offset the signed offset for the memory access * @param offset the signed offset for the memory access
* @param expectedValue the expected value of the atomic exchange * @param expectedValue the expected current value at the memory address
* @param newValue the new value of the atomic exchange * @param newValue the new value for the atomic exchange
* @param locationIdentity the identity of the memory location * @param locationIdentity the identity of the memory location
* @return {@code true} if successful. False return indicates that the actual value was not * @return {@code true} if successful. False return indicates that the actual value was not
* equal to the expected value. * 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); 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. * offset are in bytes.
* *
* @param offset the signed offset for the memory access * @param offset the signed offset for the memory access
* @param expectedValue the expected value of the atomic exchange * @param expectedValue the expected current value at the memory address
* @param newValue the new value of the atomic exchange * @param newValue the new value for the atomic exchange
* @param locationIdentity the identity of the memory location * @param locationIdentity the identity of the memory location
* @return {@code true} if successful. False return indicates that the actual value was not * @return {@code true} if successful. False return indicates that the actual value was not
* equal to the expected value. * 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); 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. * offset are in bytes.
* *
* @param offset the signed offset for the memory access * @param offset the signed offset for the memory access
* @param expectedValue the expected value of the atomic exchange * @param expectedValue the expected current value at the memory address
* @param newValue the new value of the atomic exchange * @param newValue the new value for the atomic exchange
* @param locationIdentity the identity of the memory location * @param locationIdentity the identity of the memory location
* @return {@code true} if successful. False return indicates that the actual value was not * @return {@code true} if successful. False return indicates that the actual value was not
* equal to the expected value. * equal to the expected value.

View File

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

View File

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

View File

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

View File

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

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -22,6 +22,22 @@
*/ */
package jdk.internal.vm.compiler.word; package jdk.internal.vm.compiler.word;
import jdk.internal.vm.compiler.word.impl.WordBoxFactory; import jdk.internal.vm.compiler.word.impl.WordBoxFactory;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1475,6 +1475,14 @@ public class AArch64MacroAssembler extends AArch64Assembler {
super.hint(SystemHint.NOP); 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()}. * Same as {@link #nop()}.
*/ */

View File

@ -59,6 +59,7 @@ import jdk.vm.ci.amd64.AMD64;
import jdk.vm.ci.amd64.AMD64.CPUFeature; import jdk.vm.ci.amd64.AMD64.CPUFeature;
import jdk.vm.ci.amd64.AMD64Kind; import jdk.vm.ci.amd64.AMD64Kind;
import jdk.vm.ci.code.Register; import jdk.vm.ci.code.Register;
import jdk.vm.ci.code.Register.RegisterCategory;
import jdk.vm.ci.code.TargetDescription; import jdk.vm.ci.code.TargetDescription;
import jdk.vm.ci.meta.PlatformKind; import jdk.vm.ci.meta.PlatformKind;
@ -269,8 +270,12 @@ public abstract class AMD64BaseAssembler extends Assembler {
return ((AMD64) target.arch).getFeatures().contains(feature); 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) { 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; return r.encoding & 0x7;
} }
@ -296,6 +301,10 @@ public abstract class AMD64BaseAssembler extends Assembler {
private static final int REXWRB = 0x4D; private static final int REXWRB = 0x4D;
private static final int REXWRX = 0x4E; private static final int REXWRX = 0x4E;
private static final int REXWRXB = 0x4F; 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() { protected final void rexw() {
@ -797,12 +806,17 @@ public abstract class AMD64BaseAssembler extends Assembler {
@Override @Override
public void simdPrefix(Register reg, Register nds, AMD64Address rm, int sizePrefix, int opcodeEscapePrefix, boolean isRexW) { 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 @Override
public void simdPrefix(Register dst, Register nds, Register src, int sizePrefix, int opcodeEscapePrefix, boolean isRexW) { 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); 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. * Low-level function to encode and emit the VEX prefix.
* <p> * <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 * This function automatically chooses the 2 or 3 byte encoding, based on the XBW flags and the
* m-mmmm field. * m-mmmm field.
*/ */
protected final void emitVEX(int l, int pp, int mmmmm, int w, int rxb, int vvvv) { protected final void emitVEX(int l, int pp, int mmmmm, int w, int rxb, int vvvv, boolean checkAVX) {
assert ((AMD64) target.arch).getFeatures().contains(CPUFeature.AVX) : "emitting VEX prefix on a CPU without AVX support"; 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 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"; 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 |= l << 2;
byte2 |= pp; byte2 |= pp;
emitByte(0xC5); emitByte(Prefix.VEX2);
emitByte(byte2); emitByte(byte2);
} else { } else {
// 3 byte encoding // 3 byte encoding
@ -881,7 +935,7 @@ public abstract class AMD64BaseAssembler extends Assembler {
byte3 |= l << 2; byte3 |= l << 2;
byte3 |= pp; byte3 |= pp;
emitByte(0xC4); emitByte(Prefix.VEX3);
emitByte(byte2); emitByte(byte2);
emitByte(byte3); 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) { 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); 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) { 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); emitVEX(getLFlag(size), pp, mmmmm, w, getRXB(dst, src), nds.isValid() ? nds.encoding() : 0, checkAVX);
} }
protected static final class EVEXPrefixConfig { 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. * Low-level function to encode and emit the EVEX prefix.
* <p> * <p>
@ -1021,13 +1120,13 @@ public abstract class AMD64BaseAssembler extends Assembler {
assert (rxb & 0x07) == rxb : "invalid value for EVEX.RXB"; assert (rxb & 0x07) == rxb : "invalid value for EVEX.RXB";
assert (reg & 0x1F) == reg : "invalid value for EVEX.R'"; 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 z == Z0 || z == Z1 : "invalid value for EVEX.z";
assert b == B0 || b == B1 : "invalid value for EVEX.b"; assert b == B0 || b == B1 : "invalid value for EVEX.b";
assert (aaa & 0x07) == aaa : "invalid value for EVEX.aaa"; assert (aaa & 0x07) == aaa : "invalid value for EVEX.aaa";
emitByte(0x62); emitByte(Prefix.EVEX);
int p1 = 0; int p1 = 0;
p1 |= ((rxb ^ 0x07) & 0x07) << 5; p1 |= ((rxb ^ 0x07) & 0x07) << 5;
p1 |= reg < 16 ? 0x10 : 0; p1 |= reg < 16 ? 0x10 : 0;
@ -1037,7 +1136,7 @@ public abstract class AMD64BaseAssembler extends Assembler {
int p2 = 0; int p2 = 0;
p2 |= w << 7; p2 |= w << 7;
p2 |= ((vvvvv ^ 0x0F) & 0x0F) << 3; p2 |= ((vvvvv ^ 0x0F) & 0x0F) << 3;
p2 |= 0x4; p2 |= 0x04;
p2 |= pp; p2 |= pp;
emitByte(p2); emitByte(p2);
@ -1050,6 +1149,11 @@ public abstract class AMD64BaseAssembler extends Assembler {
emitByte(p3); 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) { private static int getRXBForEVEX(Register reg, Register rm) {
int rxb = (reg == null ? 0 : reg.encoding & 0x08) >> 1; int rxb = (reg == null ? 0 : reg.encoding & 0x08) >> 1;
rxb |= (rm == null ? 0 : rm.encoding & 0x018) >> 3; 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. * 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) { 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); 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)}. * {@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) { 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); emitEVEX(getLFlag(size), pp, mm, w, getRXB(dst, src), dst.encoding, nds.isValid() ? nds.encoding() : 0, z, b, mask.isValid() ? mask.encoding : 0);
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -24,6 +24,8 @@
package org.graalvm.compiler.asm.amd64; 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.UseIncDec;
import static org.graalvm.compiler.asm.amd64.AMD64AsmOptions.UseXmmLoadAndClearUpper; import static org.graalvm.compiler.asm.amd64.AMD64AsmOptions.UseXmmLoadAndClearUpper;
import static org.graalvm.compiler.asm.amd64.AMD64AsmOptions.UseXmmRegToRegMoveAll; 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) { public void incrementq(Register reg, int value) {
if (value == Integer.MIN_VALUE) { if (value == Integer.MIN_VALUE) {
addq(reg, value); addq(reg, value);

View File

@ -191,6 +191,10 @@ public class CompilationResult {
private StackSlot customStackArea = null; 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 String name;
private final CompilationIdentifier compilationId; private final CompilationIdentifier compilationId;
@ -228,7 +232,7 @@ public class CompilationResult {
private boolean isImmutablePIC; private boolean isImmutablePIC;
public CompilationResult(CompilationIdentifier compilationId) { public CompilationResult(CompilationIdentifier compilationId) {
this(compilationId, compilationId.toString(CompilationIdentifier.Verbosity.NAME), false); this(compilationId, null, false);
} }
public CompilationResult(CompilationIdentifier compilationId, String name) { public CompilationResult(CompilationIdentifier compilationId, String name) {
@ -677,6 +681,10 @@ public class CompilationResult {
return unmodifiableList(sourceMapping); 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() { public String getName() {
return name; return name;
} }

View File

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

View File

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

View File

@ -201,6 +201,16 @@ public class AArch64ArithmeticLIRGenerator extends ArithmeticLIRGenerator implem
return result; 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) { private static PlatformKind getFloatConvertResultKind(FloatConvert op) {
switch (op) { switch (op) {
case F2I: case F2I:

View File

@ -61,6 +61,7 @@ import org.graalvm.compiler.lir.aarch64.AArch64AtomicMove.CompareAndSwapOp;
import org.graalvm.compiler.lir.aarch64.AArch64AtomicMove.AtomicReadAndWriteOp; import org.graalvm.compiler.lir.aarch64.AArch64AtomicMove.AtomicReadAndWriteOp;
import org.graalvm.compiler.lir.aarch64.AArch64Move.MembarOp; import org.graalvm.compiler.lir.aarch64.AArch64Move.MembarOp;
import org.graalvm.compiler.lir.aarch64.AArch64PauseOp; 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.LIRGenerationResult;
import org.graalvm.compiler.lir.gen.LIRGenerator; import org.graalvm.compiler.lir.gen.LIRGenerator;
import org.graalvm.compiler.phases.util.Providers; import org.graalvm.compiler.phases.util.Providers;
@ -465,9 +466,9 @@ public abstract class AArch64LIRGenerator extends LIRGenerator {
} }
@Override @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)); 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; return result;
} }
@ -513,4 +514,9 @@ public abstract class AArch64LIRGenerator extends LIRGenerator {
} }
public abstract void emitCCall(long address, CallingConvention nativeCallingConvention, Value[] args); public abstract void emitCCall(long address, CallingConvention nativeCallingConvention, Value[] args);
@Override
public void emitSpeculationFence() {
append(new AArch64SpeculativeBarrier());
}
} }

View File

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

View File

@ -25,11 +25,22 @@
package org.graalvm.compiler.core.aarch64; 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.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.LIRFrameState;
import org.graalvm.compiler.lir.aarch64.AArch64ArithmeticOp;
import org.graalvm.compiler.lir.gen.LIRGeneratorTool; import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
import org.graalvm.compiler.nodes.ConstantNode;
import org.graalvm.compiler.nodes.DeoptimizingNode; import org.graalvm.compiler.nodes.DeoptimizingNode;
import org.graalvm.compiler.nodes.NodeView; 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 org.graalvm.compiler.nodes.memory.Access;
import jdk.vm.ci.aarch64.AArch64Kind; 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(); 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 @Override
public AArch64LIRGenerator getLIRGeneratorTool() { public AArch64LIRGenerator getLIRGeneratorTool() {
return (AArch64LIRGenerator) gen; return (AArch64LIRGenerator) gen;

View File

@ -84,7 +84,10 @@ import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RMIOp;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RMOp; import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RMOp;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64Shift; import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64Shift;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.SSEOp; 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.AMD64BaseAssembler.OperandSize;
import org.graalvm.compiler.asm.amd64.AVXKind.AVXSize;
import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.core.common.NumUtil;
import org.graalvm.compiler.core.common.calc.FloatConvert; 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.AMD64ShiftOp;
import org.graalvm.compiler.lir.amd64.AMD64SignExtendOp; import org.graalvm.compiler.lir.amd64.AMD64SignExtendOp;
import org.graalvm.compiler.lir.amd64.AMD64Unary; 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.ArithmeticLIRGenerator;
import org.graalvm.compiler.lir.gen.LIRGenerator; import org.graalvm.compiler.lir.gen.LIRGenerator;
@ -931,6 +936,57 @@ public class AMD64ArithmeticLIRGenerator extends ArithmeticLIRGenerator implemen
return result; 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 @Override
public Value emitMathAbs(Value input) { public Value emitMathAbs(Value input) {
Variable result = getLIRGen().newVariable(LIRKind.combine(input)); Variable result = getLIRGen().newVariable(LIRKind.combine(input));

View File

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

View File

@ -25,8 +25,6 @@
package org.graalvm.compiler.core.amd64; 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.core.gen.NodeLIRBuilder;
import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.lir.LIRFrameState; 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.ValueNode;
import org.graalvm.compiler.nodes.calc.IntegerDivRemNode; import org.graalvm.compiler.nodes.calc.IntegerDivRemNode;
import org.graalvm.compiler.nodes.calc.IntegerDivRemNode.Op; 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.amd64.AMD64;
import jdk.vm.ci.meta.AllocatableValue; import jdk.vm.ci.meta.AllocatableValue;
@ -53,13 +46,6 @@ import jdk.vm.ci.meta.Value;
public abstract class AMD64NodeLIRBuilder extends NodeLIRBuilder { 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) { public AMD64NodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool gen, AMD64NodeMatchRules nodeMatchRules) {
super(graph, gen, nodeMatchRules); super(graph, gen, nodeMatchRules);
} }
@ -137,21 +123,4 @@ public abstract class AMD64NodeLIRBuilder extends NodeLIRBuilder {
public AMD64LIRGenerator getLIRGeneratorTool() { public AMD64LIRGenerator getLIRGeneratorTool() {
return (AMD64LIRGenerator) gen; return (AMD64LIRGenerator) gen;
} }
@Override
public void doBlockPrologue(Block block, OptionValues options) {
if (MitigateSpeculativeExecutionAttacks.getValue(options)) {
boolean hasControlSplitPredecessor = false;
for (Block b : block.getPredecessors()) {
if (b.getSuccessorCount() > 1) {
hasControlSplitPredecessor = true;
break;
}
}
boolean isStartBlock = block.getPredecessorCount() == 0;
if (hasControlSplitPredecessor || isStartBlock) {
getLIRGeneratorTool().emitLFence();
}
}
}
} }

View File

@ -78,9 +78,12 @@ import org.graalvm.compiler.nodes.memory.LIRLowerableAccess;
import org.graalvm.compiler.nodes.memory.WriteNode; import org.graalvm.compiler.nodes.memory.WriteNode;
import org.graalvm.compiler.nodes.util.GraphUtil; 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.amd64.AMD64Kind;
import jdk.vm.ci.meta.AllocatableValue; import jdk.vm.ci.meta.AllocatableValue;
import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaConstant;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.PlatformKind; import jdk.vm.ci.meta.PlatformKind;
import jdk.vm.ci.meta.Value; import jdk.vm.ci.meta.Value;
import jdk.vm.ci.meta.ValueKind; import jdk.vm.ci.meta.ValueKind;
@ -272,6 +275,81 @@ public class AMD64NodeMatchRules extends NodeMatchRules {
return getArithmeticLIRGenerator().emitLoad(to, address, state); 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 Read=access value))")
@MatchRule("(If (IntegerTest FloatingRead=access value))") @MatchRule("(If (IntegerTest FloatingRead=access value))")
public ComplexMatchResult integerTestBranchMemory(IfNode root, LIRLowerableAccess access, ValueNode value) { public ComplexMatchResult integerTestBranchMemory(IfNode root, LIRLowerableAccess access, ValueNode value) {

View File

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

View File

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

View File

@ -63,7 +63,7 @@ public final class BiDirectionalTraceBuilder {
} }
private static int compare(AbstractBlockBase<?> a, AbstractBlockBase<?> b) { 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) { private boolean processed(AbstractBlockBase<?> b) {
@ -132,7 +132,7 @@ public final class BiDirectionalTraceBuilder {
} }
private void addBlockToTrace(DebugContext debug, AbstractBlockBase<?> block) { 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()); processed.set(block.getId());
} }
@ -142,7 +142,7 @@ public final class BiDirectionalTraceBuilder {
private AbstractBlockBase<?> selectPredecessor(AbstractBlockBase<?> block) { private AbstractBlockBase<?> selectPredecessor(AbstractBlockBase<?> block) {
AbstractBlockBase<?> next = null; AbstractBlockBase<?> next = null;
for (AbstractBlockBase<?> pred : block.getPredecessors()) { 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; next = pred;
} }
} }
@ -160,7 +160,7 @@ public final class BiDirectionalTraceBuilder {
private AbstractBlockBase<?> selectSuccessor(AbstractBlockBase<?> block) { private AbstractBlockBase<?> selectSuccessor(AbstractBlockBase<?> block) {
AbstractBlockBase<?> next = null; AbstractBlockBase<?> next = null;
for (AbstractBlockBase<?> succ : block.getSuccessors()) { 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; next = succ;
} }
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -420,9 +420,9 @@ public abstract class SPARCLIRGenerator extends LIRGenerator {
} }
@Override @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)); 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; return result;
} }
@ -477,4 +477,9 @@ public abstract class SPARCLIRGenerator extends LIRGenerator {
public void emitPause() { public void emitPause() {
append(new SPARCPauseOp()); append(new SPARCPauseOp());
} }
@Override
public void emitSpeculationFence() {
throw GraalError.unimplemented();
}
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -34,7 +34,7 @@ import org.graalvm.compiler.nodes.InvokeNode;
import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
import org.graalvm.compiler.nodes.ValueNode; 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.LoadHubNode;
import org.graalvm.compiler.nodes.extended.LoadMethodNode; import org.graalvm.compiler.nodes.extended.LoadMethodNode;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -27,6 +27,8 @@ package org.graalvm.compiler.core.gen;
import static jdk.vm.ci.code.ValueUtil.asRegister; import static jdk.vm.ci.code.ValueUtil.asRegister;
import static jdk.vm.ci.code.ValueUtil.isLegal; import static jdk.vm.ci.code.ValueUtil.isLegal;
import static jdk.vm.ci.code.ValueUtil.isRegister; 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.core.common.GraalOptions.MatchExpressions;
import static org.graalvm.compiler.debug.DebugOptions.LogVerbose; import static org.graalvm.compiler.debug.DebugOptions.LogVerbose;
import static org.graalvm.compiler.lir.LIR.verifyBlock; 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) { 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 @Override
@ -372,6 +387,8 @@ public abstract class NodeLIRBuilder implements NodeLIRBuilderTool, LIRGeneratio
debug.log("interior match for %s", valueNode); debug.log("interior match for %s", valueNode);
} else if (operand instanceof ComplexMatchValue) { } else if (operand instanceof ComplexMatchValue) {
debug.log("complex match for %s", valueNode); 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; ComplexMatchValue match = (ComplexMatchValue) operand;
operand = match.evaluate(this); operand = match.evaluate(this);
if (operand != null) { if (operand != null) {

View File

@ -47,10 +47,13 @@ import org.graalvm.compiler.nodes.calc.IntegerTestNode;
import org.graalvm.compiler.nodes.calc.LeftShiftNode; import org.graalvm.compiler.nodes.calc.LeftShiftNode;
import org.graalvm.compiler.nodes.calc.MulNode; import org.graalvm.compiler.nodes.calc.MulNode;
import org.graalvm.compiler.nodes.calc.NarrowNode; 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.ObjectEqualsNode;
import org.graalvm.compiler.nodes.calc.OrNode; import org.graalvm.compiler.nodes.calc.OrNode;
import org.graalvm.compiler.nodes.calc.PointerEqualsNode; import org.graalvm.compiler.nodes.calc.PointerEqualsNode;
import org.graalvm.compiler.nodes.calc.ReinterpretNode; 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.SignExtendNode;
import org.graalvm.compiler.nodes.calc.SubNode; import org.graalvm.compiler.nodes.calc.SubNode;
import org.graalvm.compiler.nodes.calc.UnsignedRightShiftNode; 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 = WriteNode.class, inputs = {"address", "value"})
@MatchableNode(nodeClass = ZeroExtendNode.class, inputs = {"value"}) @MatchableNode(nodeClass = ZeroExtendNode.class, inputs = {"value"})
@MatchableNode(nodeClass = AndNode.class, inputs = {"x", "y"}, commutative = true) @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 = FloatEqualsNode.class, inputs = {"x", "y"}, commutative = true)
@MatchableNode(nodeClass = FloatLessThanNode.class, inputs = {"x", "y"}, commutative = true) @MatchableNode(nodeClass = FloatLessThanNode.class, inputs = {"x", "y"}, commutative = true)
@MatchableNode(nodeClass = PointerEqualsNode.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 = PiNode.class, inputs = {"object"})
@MatchableNode(nodeClass = LogicCompareAndSwapNode.class, inputs = {"address", "expectedValue", "newValue"}) @MatchableNode(nodeClass = LogicCompareAndSwapNode.class, inputs = {"address", "expectedValue", "newValue"})
@MatchableNode(nodeClass = ValueCompareAndSwapNode.class, inputs = {"address", "expectedValue", "newValue"}) @MatchableNode(nodeClass = ValueCompareAndSwapNode.class, inputs = {"address", "expectedValue", "newValue"})
@MatchableNode(nodeClass = RightShiftNode.class, inputs = {"x", "y"})
public abstract class NodeMatchRules { public abstract class NodeMatchRules {
NodeLIRBuilder lirBuilder; NodeLIRBuilder lirBuilder;

View File

@ -34,7 +34,7 @@ import org.graalvm.compiler.nodes.LogicConstantNode;
import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.phases.BasePhase; import org.graalvm.compiler.phases.BasePhase;
import org.graalvm.compiler.phases.PhaseSuite; 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; 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 * 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. * 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()); StructuredGraph graphCopy = (StructuredGraph) graph.copy(graph.getDebug());
DebugContext debug = graph.getDebug(); DebugContext debug = graph.getDebug();
try (NodeEventScope s = graphCopy.trackNodeEvents(listener)) { try (NodeEventScope s = graphCopy.trackNodeEvents(listener)) {
@ -90,7 +90,7 @@ public class GraphChangeMonitoringPhase<C extends PhaseContext> extends PhaseSui
} }
if (!filteredNodes.isEmpty()) { if (!filteredNodes.isEmpty()) {
/* rerun it on the real graph in a new Debug scope so Dump and Log can find it. */ /* 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 (NodeEventScope s = graph.trackNodeEvents(listener)) {
try (DebugContext.Scope s2 = debug.scope("WithGraphChangeMonitoring")) { try (DebugContext.Scope s2 = debug.scope("WithGraphChangeMonitoring")) {
if (debug.isDumpEnabled(DebugContext.DETAILED_LEVEL)) { if (debug.isDumpEnabled(DebugContext.DETAILED_LEVEL)) {

View File

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

View File

@ -44,6 +44,7 @@ import org.graalvm.compiler.lir.gen.LIRGenerationResult;
import org.graalvm.compiler.lir.gen.LIRGeneratorTool; import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; 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.SuitesProvider;
import org.graalvm.compiler.phases.tiers.TargetProvider; import org.graalvm.compiler.phases.tiers.TargetProvider;
import org.graalvm.compiler.phases.util.Providers; 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 * Turns a Graal {@link CompilationResult} into a {@link CompiledCode} object that can be passed
* to the VM for code installation. * 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, * @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 * @param context a custom debug context to use for the code installation
* @return a reference to the compiled and ready-to-run installed code * @return a reference to the compiled and ready-to-run installed code
* @throws BailoutException if the code installation failed * @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") @SuppressWarnings("try")
public InstalledCode createInstalledCode(DebugContext debug, ResolvedJavaMethod method, CompilationRequest compilationRequest, CompilationResult compilationResult, 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; InstalledCode installedCode;
try { try {
preCodeInstallationTasks(tasks, compilationResult, predefinedInstalledCode); preCodeInstallationTasks(tasks, compilationResult);
CompiledCode compiledCode = createCompiledCode(method, compilationRequest, compilationResult); CompiledCode compiledCode = createCompiledCode(method, compilationRequest, compilationResult, isDefault, debug.getOptions());
installedCode = getProviders().getCodeCache().installCode(method, compiledCode, predefinedInstalledCode, speculationLog, isDefault); installedCode = getProviders().getCodeCache().installCode(method, compiledCode, predefinedInstalledCode, speculationLog, isDefault);
assert predefinedInstalledCode == null || installedCode == predefinedInstalledCode; assert predefinedInstalledCode == null || installedCode == predefinedInstalledCode;
} catch (Throwable t) { } catch (Throwable t) {
@ -218,7 +222,7 @@ public abstract class Backend implements TargetProvider, ValueKindFactory<LIRKin
throw t; throw t;
} }
postCodeInstallationTasks(tasks, installedCode); postCodeInstallationTasks(tasks, compilationResult, installedCode);
return installedCode; return installedCode;
} catch (Throwable e) { } 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) { 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 { try {
for (CodeInstallationTask task : tasks) { for (CodeInstallationTask task : tasks) {
task.postProcess(installedCode); task.postProcess(compilationResult, installedCode);
} }
} catch (Throwable t) { } catch (Throwable t) {
installedCode.invalidate(); installedCode.invalidate();
@ -310,19 +314,18 @@ public abstract class Backend implements TargetProvider, ValueKindFactory<LIRKin
* Task to run before code installation. * Task to run before code installation.
* *
* @param compilationResult the code about to be installed * @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. * Task to run after the code is installed.
* *
* @param compilationResult the code about to be installed
* @param installedCode a reference to the installed code * @param installedCode a reference to the installed code
*/ */
public void postProcess(InstalledCode installedCode) { public void postProcess(CompilationResult compilationResult, InstalledCode installedCode) {
} }
/** /**

View File

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

View File

@ -39,6 +39,7 @@ import org.graalvm.compiler.options.OptionKey;
import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.serviceprovider.GraalServices; import org.graalvm.compiler.serviceprovider.GraalServices;
import org.junit.Assume; import org.junit.Assume;
import org.junit.AssumptionViolatedException;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@ -47,9 +48,20 @@ public class TimerKeyTest {
@Before @Before
public void checkCapabilities() { public void checkCapabilities() {
assumeManagementLibraryIsLoadable();
Assume.assumeTrue("skipping management interface test", GraalServices.isCurrentThreadCpuTimeSupported()); 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 * 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. * that timers for the current thread keep ticking over.

View File

@ -80,7 +80,7 @@ import jdk.vm.ci.meta.JavaMethod;
*/ */
public final class DebugContext implements AutoCloseable { public 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 GlobalMetrics NO_GLOBAL_METRIC_VALUES = null;
public static final Iterable<DebugHandlersFactory> NO_CONFIG_CUSTOMIZERS = Collections.emptyList(); 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); 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}. * Creates a {@link DebugContext}.
*/ */

View File

@ -127,8 +127,6 @@ public class DebugOptions {
@Option(help = "Enable dumping LIR, register allocation and code generation info to the C1Visualizer.", type = OptionType.Debug) @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); 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) @Option(help = "Enable dumping to the IdealGraphVisualizer.", type = OptionType.Debug)
public static final OptionKey<Boolean> PrintGraph = new OptionKey<>(true); 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) @Option(help = "Print graphs to files instead of sending them over the network.", type = OptionType.Debug)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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