8243380: Update Graal
Reviewed-by: kvn
This commit is contained in:
parent
0963050548
commit
6c3bc71079
src
jdk.aot/share/classes
jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat
jdk.tools.jaotc/src/jdk/tools/jaotc
jdk.internal.vm.compiler/share/classes
jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections
jdk.internal.vm.compiler.libgraal/src/jdk/internal/vm/compiler/libgraal
org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test
org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64
org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64
org.graalvm.compiler.asm/src/org/graalvm/compiler/asm
org.graalvm.compiler.code/src/org/graalvm/compiler/code
org.graalvm.compiler.core.aarch64.test/src/org/graalvm/compiler/core/aarch64/test
AArch64ArrayAddressTest.javaAArch64MergeExtendWithAddSubTest.javaAArch64MergeNarrowWithAddSubTest.javaAArch64TestBitAndBranchTest.javaAArch64VolatileAccessesTest.java
org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64
org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64
org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common
CompilationListenerProfiler.javaCompilerProfiler.javaGraalOptions.javaNumUtil.java
calc
spi
CodeGenProviders.javaForeignCallDescriptor.javaForeignCallSignature.javaForeignCallsProvider.javaMetaAccessExtensionProvider.java
type
util
org.graalvm.compiler.core.match.processor/src/org/graalvm/compiler/core/match/processor
org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test
ArrayCopyVirtualizationTest.javaBoxingEliminationTest.javaCheckGraalInvariants.javaConditionTest.javaGuardPrioritiesTest.javaIfCanonicalizerSwapTest.javaLateMembarInsertionTest.javaLockEliminationTest.javaLongNodeChainTest.javaMemoryGraphCanonicalizeTest.javaMemoryScheduleTest.javaNegateCanonicalizationTest.javaNodePosIteratorTest.javaSchedulingTest.javaSimpleCFGTest.javaStaticInterfaceFieldTest.javaUnsafeVirtualizationTest.javaUnschedulableGraphTest.javaVerifyBailoutUsageTest.javaVerifyDebugUsage.javaVerifyDebugUsageTest.javaVerifyVirtualizableTest.java
ea
tutorial
org.graalvm.compiler.core/src/org/graalvm/compiler/core
org.graalvm.compiler.debug.test/src/org/graalvm/compiler/debug/test
org.graalvm.compiler.debug/src/org/graalvm/compiler/debug
CompilationListener.javaDebugContext.javaDebugOptions.javaDiagnosticsOutputDirectory.javaGlobalMetrics.java
org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test
org.graalvm.compiler.graph/src/org/graalvm/compiler/graph
org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64
@ -52,8 +52,8 @@ import jdk.tools.jaotc.binformat.pecoff.JPECoffRelocObject;
|
||||
*
|
||||
* <p>
|
||||
* This class holds information necessary to create platform-specific binary containers such as
|
||||
* ELFContainer for Linux or MachOContainer for Mac OS or PEContainer
|
||||
* for MS Windows operating systems.
|
||||
* ELFContainer for Linux or MachOContainer for Mac OS or PEContainer for MS Windows operating
|
||||
* systems.
|
||||
*
|
||||
* <p>
|
||||
* Method APIs provided by this class are used to construct and populate platform-independent
|
||||
@ -300,7 +300,7 @@ public final class BinaryContainer implements SymbolTable {
|
||||
|
||||
this.codeEntryAlignment = graalHotSpotVMConfig.codeEntryAlignment;
|
||||
|
||||
this.threadLocalHandshakes = graalHotSpotVMConfig.threadLocalHandshakes;
|
||||
this.threadLocalHandshakes = graalHotSpotVMConfig.useThreadLocalPolling;
|
||||
|
||||
// Section unique name is limited to 8 characters due to limitation on Windows.
|
||||
// Name could be longer but only first 8 characters are stored on Windows.
|
||||
@ -354,7 +354,7 @@ public final class BinaryContainer implements SymbolTable {
|
||||
graphBuilderConfig.omitAssertions()));
|
||||
if (JavaVersionUtil.JAVA_SPEC < 14) {
|
||||
// See JDK-8220049. Thread local handshakes are on by default since JDK14, the command line option has been removed.
|
||||
booleanFlagsList.add(graalHotSpotVMConfig.threadLocalHandshakes);
|
||||
booleanFlagsList.add(graalHotSpotVMConfig.useThreadLocalPolling);
|
||||
}
|
||||
|
||||
ArrayList<Integer> intFlagsList = new ArrayList<>();
|
||||
@ -432,6 +432,10 @@ public final class BinaryContainer implements SymbolTable {
|
||||
return "_aot_stub_routines_crc_table_adr";
|
||||
}
|
||||
|
||||
public static String getPollingPageSymbolName() {
|
||||
return "_aot_polling_page";
|
||||
}
|
||||
|
||||
public static String getResolveStaticEntrySymbolName() {
|
||||
return "_resolve_static_entry";
|
||||
}
|
||||
@ -508,6 +512,7 @@ public final class BinaryContainer implements SymbolTable {
|
||||
createGotSymbol(getHeapEndAddressSymbolName());
|
||||
createGotSymbol(getNarrowKlassBaseAddressSymbolName());
|
||||
createGotSymbol(getNarrowOopBaseAddressSymbolName());
|
||||
createGotSymbol(getPollingPageSymbolName());
|
||||
createGotSymbol(getLogOfHeapRegionGrainBytesSymbolName());
|
||||
createGotSymbol(getInlineContiguousAllocationSupportedSymbolName());
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -33,6 +33,7 @@ import org.graalvm.compiler.code.CompilationResult;
|
||||
import org.graalvm.compiler.core.GraalCompilerOptions;
|
||||
import org.graalvm.compiler.debug.DebugContext;
|
||||
import org.graalvm.compiler.debug.DebugContext.Activation;
|
||||
import org.graalvm.compiler.debug.DebugContext.Builder;
|
||||
import org.graalvm.compiler.debug.TTY;
|
||||
import org.graalvm.compiler.options.OptionValues;
|
||||
import org.graalvm.compiler.printer.GraalDebugHandlersFactory;
|
||||
@ -118,7 +119,7 @@ final class AOTCompilationTask implements Runnable, Comparable<Object> {
|
||||
CompilationResult compResult = null;
|
||||
final long startTime = System.currentTimeMillis();
|
||||
SnippetReflectionProvider snippetReflection = aotBackend.getProviders().getSnippetReflection();
|
||||
try (DebugContext debug = DebugContext.create(graalOptions, new GraalDebugHandlersFactory(snippetReflection)); Activation a = debug.activate()) {
|
||||
try (DebugContext debug = new Builder(graalOptions, new GraalDebugHandlersFactory(snippetReflection)).build(); Activation a = debug.activate()) {
|
||||
compResult = aotBackend.compileMethod(method, debug);
|
||||
}
|
||||
final long endTime = System.currentTimeMillis();
|
||||
|
@ -26,6 +26,7 @@
|
||||
package jdk.tools.jaotc;
|
||||
|
||||
import org.graalvm.compiler.bytecode.Bytecodes;
|
||||
import org.graalvm.compiler.hotspot.HotSpotMarkId;
|
||||
|
||||
import jdk.vm.ci.code.BytecodePosition;
|
||||
import jdk.vm.ci.code.site.Call;
|
||||
@ -67,11 +68,11 @@ final class CallInfo {
|
||||
}
|
||||
|
||||
static boolean isVirtualCall(CompiledMethodInfo methodInfo, Call call) {
|
||||
return isInvokeVirtual(call) && !methodInfo.hasMark(call, MarkId.INVOKESPECIAL) && !isStaticTarget(call);
|
||||
return isInvokeVirtual(call) && !methodInfo.hasMark(call, HotSpotMarkId.INVOKESPECIAL) && !isStaticTarget(call);
|
||||
}
|
||||
|
||||
static boolean isOptVirtualCall(CompiledMethodInfo methodInfo, Call call) {
|
||||
return isInvokeVirtual(call) && methodInfo.hasMark(call, MarkId.INVOKESPECIAL);
|
||||
return isInvokeVirtual(call) && methodInfo.hasMark(call, HotSpotMarkId.INVOKESPECIAL);
|
||||
}
|
||||
|
||||
private static boolean isJavaCall(Call call) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2020, 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
|
||||
@ -27,7 +27,8 @@ package jdk.tools.jaotc;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import jdk.vm.ci.code.site.Mark;
|
||||
import org.graalvm.compiler.code.CompilationResult;
|
||||
import org.graalvm.compiler.hotspot.HotSpotMarkId;
|
||||
|
||||
final class CodeOffsets {
|
||||
private final int entry;
|
||||
@ -42,34 +43,32 @@ final class CodeOffsets {
|
||||
this.deoptHandler = deoptHandler;
|
||||
}
|
||||
|
||||
static CodeOffsets buildFrom(List<Mark> marks) {
|
||||
static CodeOffsets buildFrom(List<CompilationResult.CodeMark> marks) {
|
||||
int entry = 0;
|
||||
int verifiedEntry = 0;
|
||||
int exceptionHandler = -1;
|
||||
int deoptHandler = -1;
|
||||
|
||||
for (Mark mark : marks) {
|
||||
if (mark.id instanceof Integer) {
|
||||
MarkId markId = MarkId.getEnum((int) mark.id);
|
||||
switch (markId) {
|
||||
case UNVERIFIED_ENTRY:
|
||||
entry = mark.pcOffset;
|
||||
break;
|
||||
case VERIFIED_ENTRY:
|
||||
verifiedEntry = mark.pcOffset;
|
||||
break;
|
||||
case OSR_ENTRY:
|
||||
// Unhandled
|
||||
break;
|
||||
case EXCEPTION_HANDLER_ENTRY:
|
||||
exceptionHandler = mark.pcOffset;
|
||||
break;
|
||||
case DEOPT_HANDLER_ENTRY:
|
||||
deoptHandler = mark.pcOffset;
|
||||
break;
|
||||
default:
|
||||
break; // Ignore others
|
||||
}
|
||||
for (CompilationResult.CodeMark mark : marks) {
|
||||
HotSpotMarkId markId = (HotSpotMarkId) mark.id;
|
||||
switch (markId) {
|
||||
case UNVERIFIED_ENTRY:
|
||||
entry = mark.pcOffset;
|
||||
break;
|
||||
case VERIFIED_ENTRY:
|
||||
verifiedEntry = mark.pcOffset;
|
||||
break;
|
||||
case OSR_ENTRY:
|
||||
// Unhandled
|
||||
break;
|
||||
case EXCEPTION_HANDLER_ENTRY:
|
||||
exceptionHandler = mark.pcOffset;
|
||||
break;
|
||||
case DEOPT_HANDLER_ENTRY:
|
||||
deoptHandler = mark.pcOffset;
|
||||
break;
|
||||
default:
|
||||
break; // Ignore others
|
||||
}
|
||||
}
|
||||
return new CodeOffsets(entry, verifiedEntry, exceptionHandler, deoptHandler);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2020, 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
|
||||
@ -25,17 +25,17 @@
|
||||
|
||||
package jdk.tools.jaotc;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.graalvm.compiler.code.CompilationResult;
|
||||
import org.graalvm.compiler.hotspot.HotSpotMarkId;
|
||||
|
||||
import jdk.tools.jaotc.AOTCompiledClass.AOTKlassData;
|
||||
import jdk.tools.jaotc.binformat.BinaryContainer;
|
||||
import jdk.tools.jaotc.binformat.ReadOnlyDataContainer;
|
||||
import jdk.tools.jaotc.AOTCompiledClass.AOTKlassData;
|
||||
import org.graalvm.compiler.code.CompilationResult;
|
||||
|
||||
import jdk.vm.ci.code.site.Mark;
|
||||
import jdk.vm.ci.code.site.Site;
|
||||
import jdk.vm.ci.code.site.Call;
|
||||
import jdk.vm.ci.hotspot.HotSpotCompiledCode;
|
||||
import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
|
||||
|
||||
@ -306,23 +306,11 @@ final class CompiledMethodInfo {
|
||||
return null;
|
||||
}
|
||||
|
||||
boolean hasMark(Site call, MarkId id) {
|
||||
for (Mark m : compilationResult.getMarks()) {
|
||||
int adjOffset = m.pcOffset;
|
||||
if (archStr.equals("aarch64")) {
|
||||
// The mark is at the end of a group of three instructions:
|
||||
// adrp; add; ldr
|
||||
adjOffset += 12;
|
||||
} else {
|
||||
// X64-specific code.
|
||||
// Call instructions are aligned to 8
|
||||
// bytes - 1 on x86 to patch address atomically,
|
||||
adjOffset = (adjOffset & (-8)) + 7;
|
||||
}
|
||||
// Mark points before aligning nops.
|
||||
if ((call.pcOffset == adjOffset) && MarkId.getEnum((int) m.id) == id) {
|
||||
return true;
|
||||
}
|
||||
boolean hasMark(Call call, HotSpotMarkId id) {
|
||||
assert id == HotSpotMarkId.INVOKESTATIC || id == HotSpotMarkId.INVOKESPECIAL;
|
||||
CompilationResult.CodeMark mark = compilationResult.getAssociatedMark(call);
|
||||
if (mark != null) {
|
||||
return mark.id == id;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2020, 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
|
||||
@ -25,6 +25,8 @@
|
||||
|
||||
package jdk.tools.jaotc;
|
||||
|
||||
import org.graalvm.compiler.hotspot.HotSpotMarkId;
|
||||
|
||||
import jdk.tools.jaotc.binformat.BinaryContainer;
|
||||
import jdk.tools.jaotc.binformat.Symbol;
|
||||
import jdk.vm.ci.code.site.Call;
|
||||
@ -136,7 +138,7 @@ final class JavaCallSiteRelocationSymbol extends CallSiteRelocationSymbol {
|
||||
private static String getResolveSymbolName(CompiledMethodInfo mi, Call call) {
|
||||
String resolveSymbolName;
|
||||
if (CallInfo.isStaticCall(call)) {
|
||||
assert mi.hasMark(call, MarkId.INVOKESTATIC);
|
||||
assert mi.hasMark(call, HotSpotMarkId.INVOKESTATIC);
|
||||
resolveSymbolName = BinaryContainer.getResolveStaticEntrySymbolName();
|
||||
} else if (CallInfo.isSpecialCall(call)) {
|
||||
resolveSymbolName = BinaryContainer.getResolveOptVirtualEntrySymbolName();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2020, 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
|
||||
@ -31,6 +31,8 @@ import static org.graalvm.compiler.hotspot.meta.HotSpotAOTProfilingPlugin.Option
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@ -39,13 +41,12 @@ import java.util.ListIterator;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.stream.Stream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
|
||||
import org.graalvm.compiler.api.runtime.GraalJVMCICompiler;
|
||||
import org.graalvm.compiler.debug.DebugContext;
|
||||
import org.graalvm.compiler.debug.DebugContext.Activation;
|
||||
import org.graalvm.compiler.debug.DebugContext.Builder;
|
||||
import org.graalvm.compiler.hotspot.CompilerConfigurationFactory;
|
||||
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
|
||||
import org.graalvm.compiler.hotspot.HotSpotGraalCompilerFactory;
|
||||
@ -232,12 +233,12 @@ public final class Main {
|
||||
// The GC names are spelled the same in both enums, so no clever remapping is needed
|
||||
// here.
|
||||
String name = "CollectedHeap::" + graalGC.name();
|
||||
int gc = graalHotSpotVMConfig.getConstant(name, Integer.class, def);
|
||||
int gc = graalHotSpotVMConfig.getConstant(name, Integer.class, def, true);
|
||||
|
||||
BinaryContainer binaryContainer = new BinaryContainer(graalOptions, graalHotSpotVMConfig, graphBuilderConfig, gc, JVM_VERSION);
|
||||
DataBuilder dataBuilder = new DataBuilder(this, backend, classes, binaryContainer);
|
||||
|
||||
try (DebugContext debug = DebugContext.create(graalOptions, new GraalDebugHandlersFactory(snippetReflection)); Activation a = debug.activate()) {
|
||||
try (DebugContext debug = new Builder(graalOptions, new GraalDebugHandlersFactory(snippetReflection)).build(); Activation a = debug.activate()) {
|
||||
dataBuilder.prepareData(debug);
|
||||
}
|
||||
|
||||
|
@ -1,79 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2020, 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 jdk.tools.jaotc;
|
||||
|
||||
import java.util.HashMap;
|
||||
import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
|
||||
|
||||
/**
|
||||
* Constants used to mark special positions in code being installed into the code cache by Graal C++
|
||||
* code.
|
||||
*/
|
||||
enum MarkId {
|
||||
VERIFIED_ENTRY("CodeInstaller::VERIFIED_ENTRY"),
|
||||
UNVERIFIED_ENTRY("CodeInstaller::UNVERIFIED_ENTRY"),
|
||||
OSR_ENTRY("CodeInstaller::OSR_ENTRY"),
|
||||
EXCEPTION_HANDLER_ENTRY("CodeInstaller::EXCEPTION_HANDLER_ENTRY"),
|
||||
DEOPT_HANDLER_ENTRY("CodeInstaller::DEOPT_HANDLER_ENTRY"),
|
||||
INVOKEINTERFACE("CodeInstaller::INVOKEINTERFACE"),
|
||||
INVOKEVIRTUAL("CodeInstaller::INVOKEVIRTUAL"),
|
||||
INVOKESTATIC("CodeInstaller::INVOKESTATIC"),
|
||||
INVOKESPECIAL("CodeInstaller::INVOKESPECIAL"),
|
||||
INLINE_INVOKE("CodeInstaller::INLINE_INVOKE"),
|
||||
POLL_NEAR("CodeInstaller::POLL_NEAR"),
|
||||
POLL_RETURN_NEAR("CodeInstaller::POLL_RETURN_NEAR"),
|
||||
POLL_FAR("CodeInstaller::POLL_FAR"),
|
||||
POLL_RETURN_FAR("CodeInstaller::POLL_RETURN_FAR"),
|
||||
CARD_TABLE_ADDRESS("CodeInstaller::CARD_TABLE_ADDRESS"),
|
||||
HEAP_TOP_ADDRESS("CodeInstaller::HEAP_TOP_ADDRESS"),
|
||||
HEAP_END_ADDRESS("CodeInstaller::HEAP_END_ADDRESS"),
|
||||
NARROW_KLASS_BASE_ADDRESS("CodeInstaller::NARROW_KLASS_BASE_ADDRESS"),
|
||||
NARROW_OOP_BASE_ADDRESS("CodeInstaller::NARROW_OOP_BASE_ADDRESS"),
|
||||
CRC_TABLE_ADDRESS("CodeInstaller::CRC_TABLE_ADDRESS"),
|
||||
LOG_OF_HEAP_REGION_GRAIN_BYTES("CodeInstaller::LOG_OF_HEAP_REGION_GRAIN_BYTES"),
|
||||
INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED("CodeInstaller::INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED");
|
||||
|
||||
private final int value;
|
||||
private static HashMap<Integer, MarkId> lookup = new HashMap<>();
|
||||
|
||||
static {
|
||||
for (MarkId e : values()) {
|
||||
lookup.put(e.value, e);
|
||||
}
|
||||
}
|
||||
|
||||
MarkId(String name) {
|
||||
this.value = (int) (long) HotSpotJVMCIRuntime.runtime().getConfigStore().getConstants().get(name);
|
||||
}
|
||||
|
||||
static MarkId getEnum(int value) {
|
||||
MarkId e = lookup.get(value);
|
||||
if (e == null) {
|
||||
throw new InternalError("Unknown enum value: " + value);
|
||||
}
|
||||
return e;
|
||||
}
|
||||
}
|
@ -25,11 +25,13 @@
|
||||
|
||||
package jdk.tools.jaotc;
|
||||
|
||||
import org.graalvm.compiler.code.CompilationResult;
|
||||
import org.graalvm.compiler.hotspot.HotSpotMarkId;
|
||||
|
||||
import jdk.tools.jaotc.binformat.BinaryContainer;
|
||||
import jdk.tools.jaotc.binformat.Relocation;
|
||||
import jdk.tools.jaotc.binformat.Relocation.RelocType;
|
||||
import jdk.tools.jaotc.binformat.Symbol;
|
||||
|
||||
import jdk.vm.ci.code.site.Mark;
|
||||
|
||||
final class MarkProcessor {
|
||||
@ -48,8 +50,8 @@ final class MarkProcessor {
|
||||
* @param mark mark being processed
|
||||
*/
|
||||
@SuppressWarnings("fallthrough")
|
||||
void process(CompiledMethodInfo methodInfo, Mark mark) {
|
||||
MarkId markId = MarkId.getEnum((int) mark.id);
|
||||
void process(CompiledMethodInfo methodInfo, CompilationResult.CodeMark mark) {
|
||||
HotSpotMarkId markId = (HotSpotMarkId) mark.id;
|
||||
switch (markId) {
|
||||
case EXCEPTION_HANDLER_ENTRY:
|
||||
case DEOPT_HANDLER_ENTRY:
|
||||
@ -62,24 +64,19 @@ final class MarkProcessor {
|
||||
}
|
||||
// fallthrough
|
||||
case CARD_TABLE_ADDRESS:
|
||||
case HEAP_TOP_ADDRESS:
|
||||
case HEAP_END_ADDRESS:
|
||||
case NARROW_KLASS_BASE_ADDRESS:
|
||||
case NARROW_OOP_BASE_ADDRESS:
|
||||
case CRC_TABLE_ADDRESS:
|
||||
case LOG_OF_HEAP_REGION_GRAIN_BYTES:
|
||||
case INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED:
|
||||
String vmSymbolName;
|
||||
switch (markId) {
|
||||
case POLL_FAR:
|
||||
case POLL_RETURN_FAR:
|
||||
vmSymbolName = BinaryContainer.getPollingPageSymbolName();
|
||||
break;
|
||||
case CARD_TABLE_ADDRESS:
|
||||
vmSymbolName = BinaryContainer.getCardTableAddressSymbolName();
|
||||
break;
|
||||
case HEAP_TOP_ADDRESS:
|
||||
vmSymbolName = BinaryContainer.getHeapTopAddressSymbolName();
|
||||
break;
|
||||
case HEAP_END_ADDRESS:
|
||||
vmSymbolName = BinaryContainer.getHeapEndAddressSymbolName();
|
||||
break;
|
||||
case NARROW_KLASS_BASE_ADDRESS:
|
||||
vmSymbolName = BinaryContainer.getNarrowKlassBaseAddressSymbolName();
|
||||
break;
|
||||
@ -92,9 +89,6 @@ final class MarkProcessor {
|
||||
case LOG_OF_HEAP_REGION_GRAIN_BYTES:
|
||||
vmSymbolName = BinaryContainer.getLogOfHeapRegionGrainBytesSymbolName();
|
||||
break;
|
||||
case INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED:
|
||||
vmSymbolName = BinaryContainer.getInlineContiguousAllocationSupportedSymbolName();
|
||||
break;
|
||||
default:
|
||||
throw new InternalError("Unhandled mark: " + mark);
|
||||
}
|
||||
@ -109,6 +103,7 @@ final class MarkProcessor {
|
||||
case VERIFIED_ENTRY:
|
||||
case UNVERIFIED_ENTRY:
|
||||
case OSR_ENTRY:
|
||||
case FRAME_COMPLETE:
|
||||
case INVOKEINTERFACE:
|
||||
case INVOKEVIRTUAL:
|
||||
case INVOKESTATIC:
|
||||
|
@ -236,7 +236,7 @@ final class MetadataBuilder {
|
||||
infopointProcessor.process(methodInfo, infoPoint);
|
||||
}
|
||||
|
||||
for (Mark mark : compilationResult.getMarks()) {
|
||||
for (CompilationResult.CodeMark mark : compilationResult.getMarks()) {
|
||||
markProcessor.process(methodInfo, mark);
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2020, 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
|
||||
@ -45,7 +45,26 @@ import java.util.Map;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
/**
|
||||
* Memory efficient map data structure.
|
||||
* Memory efficient map data structure that dynamically changes its representation depending on the
|
||||
* number of entries and is specially optimized for small number of entries. It keeps elements in a
|
||||
* linear list without any hashing when the number of entries is small. Should an actual hash data
|
||||
* structure be necessary, it tries to fit the hash value into as few bytes as possible. In contrast
|
||||
* to {@link java.util.HashMap}, it avoids allocating an extra node object per entry and rather
|
||||
* keeps values always in a plain array. See {@link EconomicMapImpl} for implementation details and
|
||||
* exact thresholds when its representation changes.
|
||||
*
|
||||
* It supports a {@code null} value, but it does not support adding or looking up a {@code null}
|
||||
* key. Operations {@code get} and {@code put} provide constant-time performance on average if
|
||||
* repeatedly performed. They can however trigger an operation growing or compressing the data
|
||||
* structure, which is linear in the number of elements. Iteration is also linear in the number of
|
||||
* elements.
|
||||
*
|
||||
* The implementation is not synchronized. If multiple threads want to access the data structure, it
|
||||
* requires manual synchronization, for example using {@link java.util.Collections#synchronizedMap}.
|
||||
* There is also no extra precaution to detect concurrent modification while iterating.
|
||||
*
|
||||
* Different strategies for the equality comparison can be configured by providing a
|
||||
* {@link Equivalence} configuration object.
|
||||
*
|
||||
* @since 19.0
|
||||
*/
|
||||
@ -53,7 +72,8 @@ public interface EconomicMap<K, V> extends UnmodifiableEconomicMap<K, V> {
|
||||
|
||||
/**
|
||||
* Associates {@code value} with {@code key} in this map. If the map previously contained a
|
||||
* mapping for {@code key}, the old value is replaced by {@code value}.
|
||||
* mapping for {@code key}, the old value is replaced by {@code value}. While the {@code value}
|
||||
* may be {@code null}, the {@code key} must not be {code null}.
|
||||
*
|
||||
* @return the previous value associated with {@code key}, or {@code null} if there was no
|
||||
* mapping for {@code key}.
|
||||
@ -94,7 +114,7 @@ public interface EconomicMap<K, V> extends UnmodifiableEconomicMap<K, V> {
|
||||
|
||||
/**
|
||||
* Removes the mapping for {@code key} from this map if it is present. The map will not contain
|
||||
* a mapping for {@code key} once the call returns.
|
||||
* a mapping for {@code key} once the call returns. The {@code key} must not be {@code null}.
|
||||
*
|
||||
* @return the previous value associated with {@code key}, or {@code null} if there was no
|
||||
* mapping for {@code key}.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2020, 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
|
||||
@ -41,7 +41,6 @@
|
||||
package jdk.internal.vm.compiler.collections;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Objects;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
/**
|
||||
@ -240,7 +239,7 @@ final class EconomicMapImpl<K, V> implements EconomicMap<K, V>, EconomicSet<K> {
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public V get(K key) {
|
||||
Objects.requireNonNull(key);
|
||||
checkKeyNonNull(key);
|
||||
|
||||
int index = find(key);
|
||||
if (index != -1) {
|
||||
@ -420,9 +419,7 @@ final class EconomicMapImpl<K, V> implements EconomicMap<K, V>, EconomicSet<K> {
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public V put(K key, V value) {
|
||||
if (key == null) {
|
||||
throw new UnsupportedOperationException("null not supported as key!");
|
||||
}
|
||||
checkKeyNonNull(key);
|
||||
int index = find(key);
|
||||
if (index != -1) {
|
||||
Object oldValue = getValue(index);
|
||||
@ -622,9 +619,7 @@ final class EconomicMapImpl<K, V> implements EconomicMap<K, V>, EconomicSet<K> {
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public V removeKey(K key) {
|
||||
if (key == null) {
|
||||
throw new UnsupportedOperationException("null not supported as key!");
|
||||
}
|
||||
checkKeyNonNull(key);
|
||||
int index;
|
||||
if (hasHashArray()) {
|
||||
index = this.findAndRemoveHash(key);
|
||||
@ -640,6 +635,12 @@ final class EconomicMapImpl<K, V> implements EconomicMap<K, V>, EconomicSet<K> {
|
||||
return null;
|
||||
}
|
||||
|
||||
private void checkKeyNonNull(K key) {
|
||||
if (key == null) {
|
||||
throw new UnsupportedOperationException("null not supported as key!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the element at the specific index and returns the index of the next element. This can
|
||||
* be a different value if graph compression was triggered.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2020, 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
|
||||
@ -41,7 +41,8 @@
|
||||
package jdk.internal.vm.compiler.collections;
|
||||
|
||||
/**
|
||||
* Unmodifiable memory efficient map data structure.
|
||||
* Unmodifiable memory efficient map. See {@link EconomicMap} for the underlying data structure and
|
||||
* its properties.
|
||||
*
|
||||
* @since 19.0
|
||||
*/
|
||||
@ -49,7 +50,7 @@ public interface UnmodifiableEconomicMap<K, V> {
|
||||
|
||||
/**
|
||||
* Returns the value to which {@code key} is mapped, or {@code null} if this map contains no
|
||||
* mapping for {@code key}.
|
||||
* mapping for {@code key}. The {@code key} must not be {@code null}.
|
||||
*
|
||||
* @since 19.0
|
||||
*/
|
||||
@ -57,7 +58,7 @@ public interface UnmodifiableEconomicMap<K, V> {
|
||||
|
||||
/**
|
||||
* Returns the value to which {@code key} is mapped, or {@code defaultValue} if this map
|
||||
* contains no mapping for {@code key}.
|
||||
* contains no mapping for {@code key}. The {@code key} must not be {@code null}.
|
||||
*
|
||||
* @since 19.0
|
||||
*/
|
||||
@ -70,7 +71,8 @@ public interface UnmodifiableEconomicMap<K, V> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if this map contains a mapping for {@code key}.
|
||||
* Returns {@code true} if this map contains a mapping for {@code key}. Returns always
|
||||
* {@code false} if the {@code key} is {@code null}.
|
||||
*
|
||||
* @since 19.0
|
||||
*/
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -24,7 +24,8 @@
|
||||
|
||||
package jdk.internal.vm.compiler.libgraal;
|
||||
|
||||
import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
|
||||
import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
|
||||
|
||||
import jdk.vm.ci.hotspot.HotSpotSpeculationLog;
|
||||
import jdk.vm.ci.services.Services;
|
||||
|
||||
@ -33,8 +34,13 @@ import jdk.vm.ci.services.Services;
|
||||
*/
|
||||
public class LibGraal {
|
||||
|
||||
static {
|
||||
// Initialize JVMCI to ensure JVMCI opens its packages to Graal.
|
||||
Services.initializeJVMCI();
|
||||
}
|
||||
|
||||
public static boolean isAvailable() {
|
||||
return inLibGraal() || isolate != 0L;
|
||||
return inLibGraal() || theIsolate != 0L;
|
||||
}
|
||||
|
||||
public static boolean isSupported() {
|
||||
@ -45,67 +51,63 @@ public class LibGraal {
|
||||
return Services.IS_IN_NATIVE_IMAGE;
|
||||
}
|
||||
|
||||
public static void registerNativeMethods(HotSpotJVMCIRuntime runtime, Class<?> clazz) {
|
||||
public static void registerNativeMethods(Class<?> clazz) {
|
||||
if (clazz.isPrimitive()) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
if (inLibGraal() || !isAvailable()) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
runtime.registerNativeMethods(clazz);
|
||||
runtime().registerNativeMethods(clazz);
|
||||
}
|
||||
|
||||
public static long translate(HotSpotJVMCIRuntime runtime, Object obj) {
|
||||
public static long translate(Object obj) {
|
||||
if (!isAvailable()) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
if (!inLibGraal() && LibGraalScope.currentScope.get() == null) {
|
||||
throw new IllegalStateException("Not within a " + LibGraalScope.class.getName());
|
||||
}
|
||||
return runtime.translate(obj);
|
||||
return runtime().translate(obj);
|
||||
}
|
||||
|
||||
public static <T> T unhand(HotSpotJVMCIRuntime runtime, Class<T> type, long handle) {
|
||||
public static <T> T unhand(Class<T> type, long handle) {
|
||||
if (!isAvailable()) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
if (!inLibGraal() && LibGraalScope.currentScope.get() == null) {
|
||||
throw new IllegalStateException("Not within a " + LibGraalScope.class.getName());
|
||||
}
|
||||
return runtime.unhand(type, handle);
|
||||
return runtime().unhand(type, handle);
|
||||
}
|
||||
|
||||
private static long initializeLibgraal() {
|
||||
try {
|
||||
// Initialize JVMCI to ensure JVMCI opens its packages to
|
||||
// Graal otherwise the call to HotSpotJVMCIRuntime.runtime()
|
||||
// below will fail on JDK13+.
|
||||
Services.initializeJVMCI();
|
||||
|
||||
HotSpotJVMCIRuntime runtime = HotSpotJVMCIRuntime.runtime();
|
||||
long[] nativeInterface = runtime.registerNativeMethods(LibGraal.class);
|
||||
return nativeInterface[1];
|
||||
long[] javaVMInfo = runtime().registerNativeMethods(LibGraalScope.class);
|
||||
return javaVMInfo[1];
|
||||
} catch (UnsupportedOperationException e) {
|
||||
return 0L;
|
||||
}
|
||||
}
|
||||
|
||||
static final long isolate = Services.IS_BUILDING_NATIVE_IMAGE ? 0L : initializeLibgraal();
|
||||
static final long theIsolate = Services.IS_BUILDING_NATIVE_IMAGE ? 0L : initializeLibgraal();
|
||||
|
||||
static boolean isCurrentThreadAttached(HotSpotJVMCIRuntime runtime) {
|
||||
return runtime.isCurrentThreadAttached();
|
||||
static boolean isCurrentThreadAttached() {
|
||||
return runtime().isCurrentThreadAttached();
|
||||
}
|
||||
|
||||
public static boolean attachCurrentThread(HotSpotJVMCIRuntime runtime, boolean isDaemon) {
|
||||
return runtime.attachCurrentThread(isDaemon);
|
||||
public static boolean attachCurrentThread(boolean isDaemon, long[] isolate) {
|
||||
if (isolate != null) {
|
||||
isolate[0] = LibGraal.theIsolate;
|
||||
}
|
||||
return runtime().attachCurrentThread(isDaemon);
|
||||
}
|
||||
|
||||
public static void detachCurrentThread(HotSpotJVMCIRuntime runtime) {
|
||||
runtime.detachCurrentThread();
|
||||
public static boolean detachCurrentThread(boolean release) {
|
||||
runtime().detachCurrentThread();
|
||||
return false;
|
||||
}
|
||||
|
||||
static native long getCurrentIsolateThread(long iso);
|
||||
|
||||
public static long getFailedSpeculationsAddress(HotSpotSpeculationLog log) {
|
||||
return log.getFailedSpeculationsAddress();
|
||||
}
|
||||
|
149
src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.libgraal/src/jdk/internal/vm/compiler/libgraal/LibGraalIsolate.java
Normal file
149
src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.libgraal/src/jdk/internal/vm/compiler/libgraal/LibGraalIsolate.java
Normal file
@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright (c) 2020, 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 jdk.internal.vm.compiler.libgraal;
|
||||
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* Represents a single libgraal isolate. All {@link LibGraalObject}s have a {@link LibGraalIsolate}
|
||||
* context.
|
||||
*/
|
||||
public final class LibGraalIsolate {
|
||||
|
||||
final long address;
|
||||
|
||||
private static final Map<Long, LibGraalIsolate> isolates = new HashMap<>();
|
||||
|
||||
static synchronized LibGraalIsolate forAddress(long isolateAddress) {
|
||||
return isolates.computeIfAbsent(isolateAddress, a -> new LibGraalIsolate(a));
|
||||
}
|
||||
|
||||
private LibGraalIsolate(long address) {
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the isolate associated with the current thread. The current thread must be in an
|
||||
* {@linkplain LibGraalScope opened} scope.
|
||||
*
|
||||
* @throws IllegalStateException if the current thread is not attached to libgraal
|
||||
*/
|
||||
public static LibGraalIsolate current() {
|
||||
return LibGraalScope.current().getIsolate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value corresponding to {@code key} from a key-value store of singleton objects. If
|
||||
* no value corresponding to {@code key} currently exists, then it is computed with
|
||||
* {@code supplier} and inserted in the store.
|
||||
*
|
||||
* This is used to obtain objects whose lifetime is bound to the isolate represented by this
|
||||
* object.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public synchronized <T> T getSingleton(Class<T> key, Supplier<T> supplier) {
|
||||
// Cannot use HahsMap.computeIfAbsent as it will throw a ConcurrentModificationException
|
||||
// if supplier recurses here to compute another singleton.
|
||||
if (!singletons.containsKey(key)) {
|
||||
singletons.put(key, supplier.get());
|
||||
}
|
||||
return (T) singletons.get(key);
|
||||
}
|
||||
|
||||
private final Map<Class<?>, Object> singletons = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Strong references to the {@link WeakReference} objects.
|
||||
*/
|
||||
private final Set<LibGraalIsolate.Cleaner> cleaners = Collections.newSetFromMap(new ConcurrentHashMap<>());
|
||||
|
||||
void register(LibGraalObject obj, long handle) {
|
||||
cleanHandles();
|
||||
Cleaner cref = new Cleaner(cleanersQueue, obj, handle);
|
||||
cleaners.add(cref);
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes {@link #cleanersQueue} to release any handles whose {@link LibGraalObject} objects
|
||||
* are now unreachable.
|
||||
*/
|
||||
private void cleanHandles() {
|
||||
Cleaner cleaner;
|
||||
while ((cleaner = (Cleaner) cleanersQueue.poll()) != null) {
|
||||
cleaners.remove(cleaner);
|
||||
if (!cleaner.clean()) {
|
||||
new Exception(String.format("Error releasing handle %d in isolate 0x%x", cleaner.handle, address)).printStackTrace(System.out);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Queue into which a {@link Cleaner} is enqueued when its {@link LibGraalObject} referent
|
||||
* becomes unreachable.
|
||||
*/
|
||||
private final ReferenceQueue<LibGraalObject> cleanersQueue = new ReferenceQueue<>();
|
||||
|
||||
private static final class Cleaner extends WeakReference<LibGraalObject> {
|
||||
private final long handle;
|
||||
|
||||
Cleaner(ReferenceQueue<LibGraalObject> cleanersQueue, LibGraalObject referent, long handle) {
|
||||
super(referent, cleanersQueue);
|
||||
this.handle = handle;
|
||||
}
|
||||
|
||||
boolean clean() {
|
||||
return LibGraalObject.releaseHandle(LibGraalScope.getIsolateThread(), handle);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies that the {@code JavaVM} associated with {@code isolate} has been destroyed. All
|
||||
* subsequent accesses to objects in the isolate will throw an {@link IllegalArgumentException}.
|
||||
*/
|
||||
static synchronized void remove(LibGraalIsolate isolate) {
|
||||
isolate.destroyed = true;
|
||||
LibGraalIsolate removed = isolates.remove(isolate.address);
|
||||
assert removed == isolate : "isolate already removed or overwritten: " + isolate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%s[0x%x]", getClass().getSimpleName(), address);
|
||||
}
|
||||
|
||||
private boolean destroyed;
|
||||
|
||||
public boolean isValid() {
|
||||
return !destroyed;
|
||||
}
|
||||
|
||||
}
|
93
src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.libgraal/src/jdk/internal/vm/compiler/libgraal/LibGraalObject.java
Normal file
93
src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.libgraal/src/jdk/internal/vm/compiler/libgraal/LibGraalObject.java
Normal file
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright (c) 2020, 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 jdk.internal.vm.compiler.libgraal;
|
||||
|
||||
/**
|
||||
* Encapsulates a handle to an object in a libgraal isolate where the object's lifetime is bound to
|
||||
* the lifetime of the {@link LibGraalObject} instance. At some point after a {@link LibGraalObject}
|
||||
* is garbage collected, a call is made to release the handle, allowing the libgraal object to be
|
||||
* collected.
|
||||
*/
|
||||
public class LibGraalObject {
|
||||
|
||||
static {
|
||||
if (LibGraal.isAvailable()) {
|
||||
LibGraal.registerNativeMethods(LibGraalObject.class);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle to an object in {@link #isolate}.
|
||||
*/
|
||||
private final long handle;
|
||||
|
||||
/**
|
||||
* The libgraal isolate containing {@link #handle}.
|
||||
*/
|
||||
private final LibGraalIsolate isolate;
|
||||
|
||||
/**
|
||||
* Creates a new {@link LibGraalObject}.
|
||||
*
|
||||
* @param handle handle to an object in a libgraal isolate
|
||||
*/
|
||||
protected LibGraalObject(long handle) {
|
||||
this.handle = handle;
|
||||
isolate = LibGraalScope.current().getIsolate();
|
||||
isolate.register(this, handle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the raw JNI handle wrapped by this object.
|
||||
*
|
||||
* @throw {@link IllegalArgumentException} if the isolate context for the handle has destroyed.
|
||||
*/
|
||||
public long getHandle() {
|
||||
if (!isolate.isValid()) {
|
||||
throw new IllegalArgumentException(toString());
|
||||
}
|
||||
return handle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases {@code handle} in the isolate denoted by {@code isolateThreadId}.
|
||||
*
|
||||
* @return {@code false} if {@code} is not a valid handle in the isolate
|
||||
*/
|
||||
// Implementation:
|
||||
// com.oracle.svm.graal.hotspot.libgraal.LibGraalEntryPoints.releaseHandle
|
||||
static native boolean releaseHandle(long isolateThreadId, long handle);
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String name = getClass().getSimpleName();
|
||||
Class<?> outer = getClass().getDeclaringClass();
|
||||
while (outer != null) {
|
||||
name = outer.getSimpleName() + '.' + name;
|
||||
outer = outer.getDeclaringClass();
|
||||
}
|
||||
return String.format("%s[%d]", name, handle);
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -24,37 +24,92 @@
|
||||
|
||||
package jdk.internal.vm.compiler.libgraal;
|
||||
|
||||
import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Scope for calling CEntryPoints in libgraal. {@linkplain #LibGraalScope(HotSpotJVMCIRuntime)
|
||||
* Opening} a scope attaches the current thread to libgraal and {@linkplain #close() closing} it
|
||||
* Scope for calling CEntryPoints in libgraal. {@linkplain #LibGraalScope() Opening} a scope ensures
|
||||
* the current thread is attached to libgraal and {@linkplain #close() closing} the outer most scope
|
||||
* detaches the current thread.
|
||||
*/
|
||||
public final class LibGraalScope implements AutoCloseable {
|
||||
|
||||
static final ThreadLocal<LibGraalScope> currentScope = new ThreadLocal<>();
|
||||
|
||||
/**
|
||||
* Shared state between a thread's nested scopes.
|
||||
*/
|
||||
static class Shared {
|
||||
final DetachAction detachAction;
|
||||
final LibGraalIsolate isolate;
|
||||
final long isolateThread;
|
||||
|
||||
Shared(DetachAction detachAction, LibGraalIsolate isolate, long isolateThread) {
|
||||
this.detachAction = detachAction;
|
||||
this.isolate = isolate;
|
||||
this.isolateThread = isolateThread;
|
||||
}
|
||||
}
|
||||
|
||||
private final LibGraalScope parent;
|
||||
private final boolean topLevel;
|
||||
private final HotSpotJVMCIRuntime runtime;
|
||||
private final long isolateThread;
|
||||
private final Shared shared;
|
||||
|
||||
/**
|
||||
* Gets the current scope.
|
||||
*
|
||||
* @throws IllegalStateException if the current thread is not in an {@linkplain #LibGraalScope()
|
||||
* opened} scope
|
||||
*/
|
||||
public static LibGraalScope current() {
|
||||
LibGraalScope scope = currentScope.get();
|
||||
if (scope == null) {
|
||||
throw new IllegalStateException("Not in an " + LibGraalScope.class.getSimpleName());
|
||||
}
|
||||
return scope;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the isolate thread associated with the current thread. The current thread must be in an
|
||||
* {@linkplain #LibGraalScope(HotSpotJVMCIRuntime) opened} scope.
|
||||
* {@linkplain #LibGraalScope() opened} scope.
|
||||
*
|
||||
* @returns a value that can be used for the IsolateThreadContext argument of a {@code native}
|
||||
* method {@link LibGraal#registerNativeMethods linked} to a CEntryPoint function in
|
||||
* libgraal
|
||||
* @throws IllegalStateException if not the current thread is not attached to libgraal
|
||||
* @throws IllegalStateException if the current thread is not attached to libgraal
|
||||
*/
|
||||
public static long getIsolateThread() {
|
||||
LibGraalScope scope = currentScope.get();
|
||||
if (scope == null) {
|
||||
throw new IllegalStateException("Cannot get isolate thread outside of a " + LibGraalScope.class.getSimpleName());
|
||||
}
|
||||
return scope.isolateThread;
|
||||
return current().shared.isolateThread;
|
||||
}
|
||||
|
||||
/**
|
||||
* Denotes the detach action to perform when closing a {@link LibGraalScope}.
|
||||
*/
|
||||
public enum DetachAction {
|
||||
/**
|
||||
* Detach the thread from its libgraal isolate.
|
||||
*/
|
||||
DETACH,
|
||||
|
||||
/**
|
||||
* Detach the thread from its libgraal isolate and the associated {@code JVMCIRuntime}.
|
||||
*/
|
||||
DETACH_RUNTIME,
|
||||
|
||||
/**
|
||||
* Detach the thread from its libgraal isolate and the associated {@code JVMCIRuntime}. If
|
||||
* the VM supports releasing the {@code JavaVM} associated with {@code JVMCIRuntime}s and
|
||||
* this is the last thread attached to its {@code JVMCIRuntime}, then the
|
||||
* {@code JVMCIRuntime} destroys its {@code JavaVM} instance.
|
||||
*/
|
||||
DETACH_RUNTIME_AND_RELEASE
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortcut for calling {@link #LibGraalScope(DetachAction)} with an argument of
|
||||
* {@link DetachAction#DETACH_RUNTIME}.
|
||||
*/
|
||||
public LibGraalScope() {
|
||||
this(DetachAction.DETACH_RUNTIME);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -69,28 +124,183 @@ public final class LibGraalScope implements AutoCloseable {
|
||||
* @throws IllegalStateException if libgraal is {@linkplain LibGraal#isAvailable() unavailable}
|
||||
* or {@link LibGraal#inLibGraal()} returns true
|
||||
*/
|
||||
public LibGraalScope(HotSpotJVMCIRuntime runtime) {
|
||||
public LibGraalScope(DetachAction detachAction) {
|
||||
if (LibGraal.inLibGraal() || !LibGraal.isAvailable()) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
this.runtime = runtime;
|
||||
parent = currentScope.get();
|
||||
boolean top = false;
|
||||
if (parent == null) {
|
||||
top = LibGraal.attachCurrentThread(runtime, false);
|
||||
isolateThread = LibGraal.getCurrentIsolateThread(LibGraal.isolate);
|
||||
long[] isolateBox = {0};
|
||||
boolean firstAttach = LibGraal.attachCurrentThread(false, isolateBox);
|
||||
long isolateAddress = isolateBox[0];
|
||||
LibGraalIsolate isolate = LibGraalIsolate.forAddress(isolateAddress);
|
||||
long isolateThread = getIsolateThreadIn(isolateAddress);
|
||||
shared = new Shared(firstAttach ? detachAction : null, isolate, isolateThread);
|
||||
} else {
|
||||
isolateThread = parent.isolateThread;
|
||||
shared = parent.shared;
|
||||
}
|
||||
topLevel = top;
|
||||
currentScope.set(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enters a scope for making calls into an existing libgraal isolate. If there is no existing
|
||||
* libgraal scope for the current thread, the current thread is attached to libgraal. When the
|
||||
* outer most scope is closed, the current thread is detached from libgraal.
|
||||
*
|
||||
* This must be used in a try-with-resources statement.
|
||||
*
|
||||
* This cannot be called from {@linkplain LibGraal#inLibGraal() within} libgraal.
|
||||
*
|
||||
* @throws IllegalStateException if libgraal is {@linkplain LibGraal#isAvailable() unavailable}
|
||||
* or {@link LibGraal#inLibGraal()} returns true
|
||||
*/
|
||||
public LibGraalScope(long isolateAddress) {
|
||||
if (LibGraal.inLibGraal() || !LibGraal.isAvailable()) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
parent = currentScope.get();
|
||||
if (parent == null) {
|
||||
long isolateThread = getIsolateThreadIn(isolateAddress);
|
||||
boolean alreadyAttached;
|
||||
if (isolateThread == 0L) {
|
||||
alreadyAttached = false;
|
||||
isolateThread = attachThreadTo(isolateAddress);
|
||||
} else {
|
||||
alreadyAttached = true;
|
||||
}
|
||||
LibGraalIsolate isolate = LibGraalIsolate.forAddress(isolateAddress);
|
||||
shared = new Shared(alreadyAttached ? null : DetachAction.DETACH, isolate, isolateThread);
|
||||
} else {
|
||||
shared = parent.shared;
|
||||
}
|
||||
currentScope.set(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attaches the current thread to the isolate at {@code isolateAddress}.
|
||||
*
|
||||
* @return the address of the attached IsolateThread
|
||||
*/
|
||||
// Implementation:
|
||||
// com.oracle.svm.graal.hotspot.libgraal.LibGraalEntryPoints.attachThreadTo
|
||||
static native long attachThreadTo(long isolateAddress);
|
||||
|
||||
/**
|
||||
* Detaches the current thread from the isolate at {@code isolateAddress}.
|
||||
*/
|
||||
// Implementation:
|
||||
// com.oracle.svm.graal.hotspot.libgraal.LibGraalEntryPoints.detachThreadFrom
|
||||
static native void detachThreadFrom(long isolateThreadAddress);
|
||||
|
||||
/**
|
||||
* Gets the isolate thread for the current thread in the isolate at {@code isolateAddress}.
|
||||
*
|
||||
* @return 0L if the current thread is not attached to the isolate at {@code isolateAddress}
|
||||
*/
|
||||
// Implementation:
|
||||
// com.oracle.svm.graal.hotspot.libgraal.LibGraalEntryPoints.getIsolateThreadIn
|
||||
@SuppressWarnings("unused")
|
||||
static native long getIsolateThreadIn(long isolateAddress);
|
||||
|
||||
/**
|
||||
* Gets the isolate associated with this scope.
|
||||
*/
|
||||
public LibGraalIsolate getIsolate() {
|
||||
return shared.isolate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the address of the isolate thread associated with this scope.
|
||||
*/
|
||||
public long getIsolateThreadAddress() {
|
||||
return shared.isolateThread;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
if (topLevel) {
|
||||
LibGraal.detachCurrentThread(runtime);
|
||||
if (parent == null && shared.detachAction != null) {
|
||||
if (shared.detachAction == DetachAction.DETACH) {
|
||||
detachThreadFrom(shared.isolateThread);
|
||||
} else {
|
||||
boolean isolateDestroyed = LibGraal.detachCurrentThread(shared.detachAction == DetachAction.DETACH_RUNTIME_AND_RELEASE);
|
||||
if (isolateDestroyed) {
|
||||
LibGraalIsolate.remove(shared.isolate);
|
||||
}
|
||||
}
|
||||
}
|
||||
currentScope.set(parent);
|
||||
}
|
||||
|
||||
// Shared support for the LibGraal overlays
|
||||
|
||||
/**
|
||||
* Convenience function for wrapping varargs into an array for use in calls to
|
||||
* {@link #method(Class, String, Class[][])}.
|
||||
*/
|
||||
static Class<?>[] sig(Class<?>... types) {
|
||||
return types;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the method in {@code declaringClass} with the unique name {@code name}.
|
||||
*
|
||||
* @param sigs the signatures the method may have
|
||||
*/
|
||||
static Method method(Class<?> declaringClass, String name, Class<?>[]... sigs) {
|
||||
if (sigs.length == 1 || sigs.length == 0) {
|
||||
try {
|
||||
Class<?>[] sig = sigs.length == 1 ? sigs[0] : new Class<?>[0];
|
||||
return declaringClass.getDeclaredMethod(name, sig);
|
||||
} catch (NoSuchMethodException | SecurityException e) {
|
||||
throw (NoSuchMethodError) new NoSuchMethodError(name).initCause(e);
|
||||
}
|
||||
}
|
||||
Method match = null;
|
||||
for (Method m : declaringClass.getDeclaredMethods()) {
|
||||
if (m.getName().equals(name)) {
|
||||
if (match != null) {
|
||||
throw new InternalError(String.format("Expected single method named %s, found %s and %s",
|
||||
name, match, m));
|
||||
}
|
||||
match = m;
|
||||
}
|
||||
}
|
||||
if (match == null) {
|
||||
throw new NoSuchMethodError("Cannot find method " + name + " in " + declaringClass.getName());
|
||||
}
|
||||
Class<?>[] parameterTypes = match.getParameterTypes();
|
||||
for (Class<?>[] sig : sigs) {
|
||||
if (Arrays.equals(parameterTypes, sig)) {
|
||||
return match;
|
||||
}
|
||||
}
|
||||
throw new NoSuchMethodError(String.format("Unexpected signature for %s: %s", name, Arrays.toString(parameterTypes)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the method in {@code declaringClass} with the unique name {@code name} or {@code null}
|
||||
* if not found.
|
||||
*
|
||||
* @param sigs the signatures the method may have
|
||||
*/
|
||||
static Method methodOrNull(Class<?> declaringClass, String name, Class<?>[]... sigs) {
|
||||
try {
|
||||
return method(declaringClass, name, sigs);
|
||||
} catch (NoSuchMethodError e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the method in {@code declaringClass} with the unique name {@code name} or {@code null}
|
||||
* if {@code guard == null}.
|
||||
*
|
||||
* @param sigs the signatures the method may have
|
||||
*/
|
||||
static Method methodIf(Object guard, Class<?> declaringClass, String name, Class<?>[]... sigs) {
|
||||
if (guard == null) {
|
||||
return null;
|
||||
}
|
||||
return method(declaringClass, name, sigs);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2020, 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
|
||||
@ -132,16 +132,6 @@ class TestProtectedAssembler extends AArch64Assembler {
|
||||
super.stxr(size, rs, rt, rn);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void ldar(int size, Register rt, Register rn) {
|
||||
super.ldar(size, rt, rn);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void stlr(int size, Register rt, Register rn) {
|
||||
super.stlr(size, rt, rn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ldaxr(int size, Register rt, Register rn) {
|
||||
super.ldaxr(size, rt, rn);
|
||||
@ -258,7 +248,7 @@ class TestProtectedAssembler extends AArch64Assembler {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void sub(int size, Register dst, Register src1, Register src2, ExtendType extendType, int shiftAmt) {
|
||||
public void sub(int size, Register dst, Register src1, Register src2, ExtendType extendType, int shiftAmt) {
|
||||
super.sub(size, dst, src1, src2, extendType, shiftAmt);
|
||||
}
|
||||
|
||||
|
@ -56,6 +56,7 @@ import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.CSIN
|
||||
import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.CSNEG;
|
||||
import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.DC;
|
||||
import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.DMB;
|
||||
import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.DSB;
|
||||
import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.EON;
|
||||
import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.EOR;
|
||||
import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.EXTR;
|
||||
@ -673,6 +674,7 @@ public abstract class AArch64Assembler extends Assembler {
|
||||
CLREX(0xd5033f5f),
|
||||
HINT(0xD503201F),
|
||||
DMB(0x000000A0),
|
||||
DSB(0x00000080),
|
||||
|
||||
MRS(0xD5300000),
|
||||
MSR(0xD5100000),
|
||||
@ -1402,7 +1404,7 @@ public abstract class AArch64Assembler extends Assembler {
|
||||
* @param rt general purpose register. May not be null or stackpointer.
|
||||
* @param rn general purpose register.
|
||||
*/
|
||||
protected void ldar(int size, Register rt, Register rn) {
|
||||
public void ldar(int size, Register rt, Register rn) {
|
||||
assert size == 8 || size == 16 || size == 32 || size == 64;
|
||||
int transferSize = NumUtil.log2Ceil(size / 8);
|
||||
exclusiveLoadInstruction(LDAR, rt, rn, transferSize);
|
||||
@ -1415,7 +1417,7 @@ public abstract class AArch64Assembler extends Assembler {
|
||||
* @param rt general purpose register. May not be null or stackpointer.
|
||||
* @param rn general purpose register.
|
||||
*/
|
||||
protected void stlr(int size, Register rt, Register rn) {
|
||||
public void stlr(int size, Register rt, Register rn) {
|
||||
assert size == 8 || size == 16 || size == 32 || size == 64;
|
||||
int transferSize = NumUtil.log2Ceil(size / 8);
|
||||
// Hack: Passing the zero-register means it is ignored when building the encoding.
|
||||
@ -1471,7 +1473,7 @@ public abstract class AArch64Assembler extends Assembler {
|
||||
*/
|
||||
private void exclusiveStoreInstruction(Instruction instr, Register rs, Register rt, Register rn, int log2TransferSize) {
|
||||
assert log2TransferSize >= 0 && log2TransferSize < 4;
|
||||
assert rt.getRegisterCategory().equals(CPU) && rs.getRegisterCategory().equals(CPU) && !rs.equals(rt);
|
||||
assert rt.getRegisterCategory().equals(CPU) && rs.getRegisterCategory().equals(CPU) && (instr == STLR || !rs.equals(rt));
|
||||
int transferSizeEncoding = log2TransferSize << LoadStoreTransferSizeOffset;
|
||||
emitInt(transferSizeEncoding | instr.encoding | rs2(rs) | rn(rn) | rt(rt));
|
||||
}
|
||||
@ -1992,7 +1994,7 @@ public abstract class AArch64Assembler extends Assembler {
|
||||
* @param extendType defines how src2 is extended to the same size as src1.
|
||||
* @param shiftAmt must be in range 0 to 4.
|
||||
*/
|
||||
protected void sub(int size, Register dst, Register src1, Register src2, ExtendType extendType, int shiftAmt) {
|
||||
public void sub(int size, Register dst, Register src1, Register src2, ExtendType extendType, int shiftAmt) {
|
||||
assert !dst.equals(zr);
|
||||
assert !src1.equals(zr);
|
||||
assert !src2.equals(sp);
|
||||
@ -3012,6 +3014,15 @@ public abstract class AArch64Assembler extends Assembler {
|
||||
emitInt(DMB.encoding | BarrierOp | barrierKind.encoding << BarrierKindOffset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data Synchronization Barrier.
|
||||
*
|
||||
* @param barrierKind barrier that is issued. May not be null.
|
||||
*/
|
||||
public void dsb(BarrierKind barrierKind) {
|
||||
emitInt(DSB.encoding | BarrierOp | barrierKind.encoding << BarrierKindOffset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instruction Synchronization Barrier.
|
||||
*/
|
||||
|
@ -2138,6 +2138,14 @@ public class AArch64MacroAssembler extends AArch64Assembler {
|
||||
super.hint(SystemHint.CSDB);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures current execution state is committed before continuing.
|
||||
*/
|
||||
public void fullSystemBarrier() {
|
||||
super.dsb(BarrierKind.SYSTEM);
|
||||
super.isb();
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as {@link #nop()}.
|
||||
*/
|
||||
|
@ -107,7 +107,8 @@ public class AMD64Assembler extends AMD64BaseAssembler {
|
||||
public static class Options {
|
||||
// @formatter:off
|
||||
@Option(help = "Force branch instructions to align with 32-bytes boundary, to mitigate the jcc erratum. " +
|
||||
"See https://www.intel.com/content/dam/support/us/en/documents/processors/mitigations-jump-conditional-code-erratum.pdf for more details.", type = OptionType.User)
|
||||
"See https://www.intel.com/content/dam/support/us/en/documents/processors/mitigations-jump-conditional-code-erratum.pdf for more details. " +
|
||||
"If not set explicitly, the default value will be determined according to the CPU model.", type = OptionType.User)
|
||||
public static final OptionKey<Boolean> UseBranchesWithin32ByteBoundary = new OptionKey<>(false);
|
||||
// @formatter:on
|
||||
}
|
||||
@ -120,19 +121,28 @@ public class AMD64Assembler extends AMD64BaseAssembler {
|
||||
|
||||
protected CodePatchShifter codePatchShifter = null;
|
||||
|
||||
/**
|
||||
* Constructs an assembler for the AMD64 architecture.
|
||||
*/
|
||||
public AMD64Assembler(TargetDescription target) {
|
||||
super(target);
|
||||
useBranchesWithin32ByteBoundary = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an assembler for the AMD64 architecture.
|
||||
*/
|
||||
public AMD64Assembler(TargetDescription target, OptionValues optionValues) {
|
||||
super(target);
|
||||
useBranchesWithin32ByteBoundary = Options.UseBranchesWithin32ByteBoundary.getValue(optionValues);
|
||||
}
|
||||
|
||||
public AMD64Assembler(TargetDescription target, OptionValues optionValues, boolean hasIntelJccErratum) {
|
||||
super(target);
|
||||
if (Options.UseBranchesWithin32ByteBoundary.hasBeenSet(optionValues)) {
|
||||
useBranchesWithin32ByteBoundary = Options.UseBranchesWithin32ByteBoundary.getValue(optionValues);
|
||||
} else {
|
||||
useBranchesWithin32ByteBoundary = hasIntelJccErratum;
|
||||
}
|
||||
}
|
||||
|
||||
public void setCodePatchShifter(CodePatchShifter codePatchShifter) {
|
||||
assert this.codePatchShifter == null : "overwriting existing value";
|
||||
this.codePatchShifter = codePatchShifter;
|
||||
@ -2269,6 +2279,12 @@ public class AMD64Assembler extends AMD64BaseAssembler {
|
||||
emitModRM(dst, src);
|
||||
}
|
||||
|
||||
public final void movb(Register dst, AMD64Address src) {
|
||||
prefixb(src, dst);
|
||||
emitByte(0x8A);
|
||||
emitOperandHelper(dst, src, 0);
|
||||
}
|
||||
|
||||
public final void movb(AMD64Address dst, int imm8) {
|
||||
prefix(dst);
|
||||
emitByte(0xC6);
|
||||
|
@ -63,6 +63,14 @@ public class AMD64MacroAssembler extends AMD64Assembler {
|
||||
super(target, optionValues);
|
||||
}
|
||||
|
||||
public AMD64MacroAssembler(TargetDescription target, OptionValues optionValues, boolean hasIntelJccErratum) {
|
||||
super(target, optionValues, hasIntelJccErratum);
|
||||
}
|
||||
|
||||
public final void decrementq(Register reg) {
|
||||
decrementq(reg, 1);
|
||||
}
|
||||
|
||||
public final void decrementq(Register reg, int value) {
|
||||
if (value == Integer.MIN_VALUE) {
|
||||
subq(reg, value);
|
||||
@ -101,6 +109,10 @@ public class AMD64MacroAssembler extends AMD64Assembler {
|
||||
}
|
||||
}
|
||||
|
||||
public final void incrementq(Register reg) {
|
||||
incrementq(reg, 1);
|
||||
}
|
||||
|
||||
public void incrementq(Register reg, int value) {
|
||||
if (value == Integer.MIN_VALUE) {
|
||||
addq(reg, value);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -26,5 +26,5 @@ package org.graalvm.compiler.asm;
|
||||
|
||||
public class AsmOptions {
|
||||
|
||||
public static int InitialCodeBufferSize = 232;
|
||||
public static final int InitialCodeBufferSize = 232;
|
||||
}
|
||||
|
@ -36,7 +36,9 @@ import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
|
||||
import jdk.internal.vm.compiler.collections.EconomicMap;
|
||||
import jdk.internal.vm.compiler.collections.EconomicSet;
|
||||
import jdk.internal.vm.compiler.collections.Equivalence;
|
||||
import org.graalvm.compiler.core.common.CompilationIdentifier;
|
||||
import org.graalvm.compiler.graph.NodeSourcePosition;
|
||||
|
||||
@ -194,7 +196,7 @@ public class CompilationResult {
|
||||
private final List<SourceMapping> sourceMapping = new ArrayList<>();
|
||||
private final List<DataPatch> dataPatches = new ArrayList<>();
|
||||
private final List<ExceptionHandler> exceptionHandlers = new ArrayList<>();
|
||||
private final List<Mark> marks = new ArrayList<>();
|
||||
private final List<CodeMark> marks = new ArrayList<>();
|
||||
|
||||
private int totalFrameSize = -1;
|
||||
private int maxInterpreterFrameSize = -1;
|
||||
@ -523,11 +525,13 @@ public class CompilationResult {
|
||||
* @param target the being called
|
||||
* @param debugInfo the debug info for the call
|
||||
* @param direct specifies if this is a {@linkplain Call#direct direct} call
|
||||
* @return created call object
|
||||
*/
|
||||
public void recordCall(int codePos, int size, InvokeTarget target, DebugInfo debugInfo, boolean direct) {
|
||||
public Call recordCall(int codePos, int size, InvokeTarget target, DebugInfo debugInfo, boolean direct) {
|
||||
checkOpen();
|
||||
final Call call = new Call(target, codePos, size, direct, debugInfo);
|
||||
addInfopoint(call);
|
||||
return call;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -603,9 +607,9 @@ public class CompilationResult {
|
||||
* @param codePos the position in the code that is covered by the handler
|
||||
* @param markId the identifier for this mark
|
||||
*/
|
||||
public Mark recordMark(int codePos, Object markId) {
|
||||
public CodeMark recordMark(int codePos, MarkId markId) {
|
||||
checkOpen();
|
||||
Mark mark = new Mark(codePos, markId);
|
||||
CodeMark mark = new CodeMark(codePos, markId);
|
||||
marks.add(mark);
|
||||
return mark;
|
||||
}
|
||||
@ -692,9 +696,78 @@ public class CompilationResult {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the list of marks
|
||||
* An identified mark in the generated code.
|
||||
*/
|
||||
public List<Mark> getMarks() {
|
||||
public interface MarkId {
|
||||
|
||||
/**
|
||||
* A human readable name for this mark.
|
||||
*/
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* Return the object which should be used in the {@link Mark}. On some platforms that may be
|
||||
* different than this object.
|
||||
*/
|
||||
default Object getId() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether the mark is intended to identify the end of the last instruction or the
|
||||
* beginning of the next instruction. This information is necessary if the backend needs to
|
||||
* insert instructions after the normal assembly step.
|
||||
*/
|
||||
boolean isMarkAfter();
|
||||
}
|
||||
|
||||
/**
|
||||
* An alternative to the existing {@link Mark} which isn't very flexible since it's final. This
|
||||
* enforces some API for the mark object and can be converted into the standard mark for code
|
||||
* installation if necessary.
|
||||
*/
|
||||
public static class CodeMark extends Site {
|
||||
|
||||
/**
|
||||
* An object denoting extra semantic information about the machine code position of this
|
||||
* mark.
|
||||
*/
|
||||
public final MarkId id;
|
||||
|
||||
/**
|
||||
* Creates a mark that associates {@code id} with the machine code position
|
||||
* {@code pcOffset}.
|
||||
*/
|
||||
public CodeMark(int pcOffset, MarkId id) {
|
||||
super(pcOffset);
|
||||
this.id = id;
|
||||
assert id != null : this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return id + "@" + pcOffset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj instanceof CodeMark) {
|
||||
CodeMark that = (CodeMark) obj;
|
||||
if (this.pcOffset == that.pcOffset && Objects.equals(this.id, that.id)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the list of {@link CodeMark code marks}.
|
||||
*/
|
||||
public List<CodeMark> getMarks() {
|
||||
if (marks.isEmpty()) {
|
||||
return emptyList();
|
||||
}
|
||||
@ -750,6 +823,7 @@ public class CompilationResult {
|
||||
if (annotations != null) {
|
||||
annotations.clear();
|
||||
}
|
||||
callToMark.clear();
|
||||
}
|
||||
|
||||
public void clearInfopoints() {
|
||||
@ -788,7 +862,7 @@ public class CompilationResult {
|
||||
});
|
||||
iterateAndReplace(dataPatches, pos, site -> new DataPatch(site.pcOffset + bytesToShift, site.reference, site.note));
|
||||
iterateAndReplace(exceptionHandlers, pos, site -> new ExceptionHandler(site.pcOffset + bytesToShift, site.handlerPos));
|
||||
iterateAndReplace(marks, pos, site -> new Mark(site.pcOffset + bytesToShift, site.id));
|
||||
iterateAndReplace(marks, pos, site -> new CodeMark(site.pcOffset + bytesToShift, site.id));
|
||||
if (annotations != null) {
|
||||
for (CodeAnnotation annotation : annotations) {
|
||||
int annotationPos = annotation.position;
|
||||
@ -802,9 +876,29 @@ public class CompilationResult {
|
||||
private static <T extends Site> void iterateAndReplace(List<T> sites, int pos, Function<T, T> replacement) {
|
||||
for (int i = 0; i < sites.size(); i++) {
|
||||
T site = sites.get(i);
|
||||
if (pos == site.pcOffset && site instanceof CodeMark) {
|
||||
CodeMark mark = (CodeMark) site;
|
||||
if (mark.id.isMarkAfter()) {
|
||||
// The insert point is exactly on the mark but the mark is annotating the end of
|
||||
// the last instruction, so leave it alone.
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (pos <= site.pcOffset) {
|
||||
sites.set(i, replacement.apply(site));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final EconomicMap<Call, CodeMark> callToMark = EconomicMap.create(Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE);
|
||||
|
||||
public void recordCallContext(CodeMark mark, Call call) {
|
||||
if (call != null) {
|
||||
callToMark.put(call, mark);
|
||||
}
|
||||
}
|
||||
|
||||
public CodeMark getAssociatedMark(Call call) {
|
||||
return callToMark.get(call);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2020, 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
|
||||
@ -28,6 +28,8 @@ import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.graalvm.compiler.serviceprovider.ServiceProvider;
|
||||
|
||||
import jdk.vm.ci.code.CodeCacheProvider;
|
||||
import jdk.vm.ci.code.CodeUtil;
|
||||
import jdk.vm.ci.code.CodeUtil.DefaultRefMapFormatter;
|
||||
@ -40,9 +42,6 @@ import jdk.vm.ci.code.site.Call;
|
||||
import jdk.vm.ci.code.site.DataPatch;
|
||||
import jdk.vm.ci.code.site.ExceptionHandler;
|
||||
import jdk.vm.ci.code.site.Infopoint;
|
||||
import jdk.vm.ci.code.site.Mark;
|
||||
|
||||
import org.graalvm.compiler.serviceprovider.ServiceProvider;
|
||||
|
||||
/**
|
||||
* {@link HexCodeFile} based implementation of {@link DisassemblerProvider}.
|
||||
@ -99,8 +98,8 @@ public class HexCodeFileDisassemblerProvider implements DisassemblerProvider {
|
||||
for (DataPatch site : compResult.getDataPatches()) {
|
||||
hcf.addOperandComment(site.pcOffset, "{" + site.reference.toString() + "}");
|
||||
}
|
||||
for (Mark mark : compResult.getMarks()) {
|
||||
hcf.addComment(mark.pcOffset, codeCache.getMarkName(mark));
|
||||
for (CompilationResult.CodeMark mark : compResult.getMarks()) {
|
||||
hcf.addComment(mark.pcOffset, mark.id.getName());
|
||||
}
|
||||
}
|
||||
String hcfEmbeddedString = hcf.toEmbeddedString();
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, Arm Limited. All rights reserved.
|
||||
* Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2020, Arm Limited. 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
|
||||
@ -27,7 +27,7 @@ package org.graalvm.compiler.core.aarch64.test;
|
||||
|
||||
import org.graalvm.compiler.api.directives.GraalDirectives;
|
||||
import org.graalvm.compiler.lir.LIRInstruction;
|
||||
import org.graalvm.compiler.lir.aarch64.AArch64ArithmeticOp.ExtendedAddShiftOp;
|
||||
import org.graalvm.compiler.lir.aarch64.AArch64ArithmeticOp.ExtendedAddSubShiftOp;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
@ -36,7 +36,7 @@ import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class AArch64ArrayAddressTest extends AArch64MatchRuleTest {
|
||||
private static final Predicate<LIRInstruction> predicate = op -> (op instanceof ExtendedAddShiftOp);
|
||||
private static final Predicate<LIRInstruction> predicate = op -> (op instanceof ExtendedAddSubShiftOp);
|
||||
|
||||
public static byte loadByte(byte[] arr, int n) {
|
||||
return arr[n];
|
||||
|
@ -0,0 +1,238 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, Arm Limited. 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.LIRInstruction;
|
||||
import org.graalvm.compiler.lir.aarch64.AArch64ArithmeticOp;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class AArch64MergeExtendWithAddSubTest extends AArch64MatchRuleTest {
|
||||
|
||||
private static final Predicate<LIRInstruction> PRED_EXTEND_ADD_SHIFT = op -> (op instanceof AArch64ArithmeticOp.ExtendedAddSubShiftOp && op.name().equals("ADD"));
|
||||
private static final Predicate<LIRInstruction> PRED_EXTEND_SUB_SHIFT = op -> (op instanceof AArch64ArithmeticOp.ExtendedAddSubShiftOp && op.name().equals("SUB"));
|
||||
|
||||
private static final Long[] LONG_VALUES = {-1L, 0L, 0x1234567812345678L, 0xFFFFFFFFL, 0x12L, 0x1234L, Long.MIN_VALUE, Long.MAX_VALUE};
|
||||
private static final Integer[] INT_VALUES = {-1, 0, 0x1234, 0x12345678, Integer.MIN_VALUE, Integer.MAX_VALUE};
|
||||
|
||||
private <T> void predicateExist(String[] testCases, T[] values, Predicate<LIRInstruction> predicate) {
|
||||
for (String t : testCases) {
|
||||
for (T value : values) {
|
||||
test(t, value, value);
|
||||
checkLIR(t, predicate, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public long addI2LShift(long x, long y) {
|
||||
int z = (int) y;
|
||||
return x + (((long) z) << 3);
|
||||
}
|
||||
|
||||
public long addB2LShift(long x, long y) {
|
||||
byte z = (byte) y;
|
||||
return x + (((long) z) << 2);
|
||||
}
|
||||
|
||||
public long addC2LShift(long x, long y) {
|
||||
char z = (char) y;
|
||||
return x + (((long) z) << 1);
|
||||
}
|
||||
|
||||
public long addS2LShift(long x, long y) {
|
||||
short z = (short) y;
|
||||
return x + (((long) z) << 4);
|
||||
}
|
||||
|
||||
public long subI2LShift(long x, long y) {
|
||||
int z = (int) y;
|
||||
return x - (((long) z) << 1);
|
||||
}
|
||||
|
||||
public long subB2LShift(long x, long y) {
|
||||
byte z = (byte) y;
|
||||
return x - (((long) z) << 2);
|
||||
}
|
||||
|
||||
public long subC2LShift(long x, long y) {
|
||||
char z = (char) y;
|
||||
return x - (((long) z) << 3);
|
||||
}
|
||||
|
||||
public long subS2LShift(long x, long y) {
|
||||
short z = (short) y;
|
||||
return x - (((long) z) << 4);
|
||||
}
|
||||
|
||||
public long addI2L(long x, long y) {
|
||||
int z = (int) y;
|
||||
return x + z;
|
||||
}
|
||||
|
||||
public long addB2L(long x, long y) {
|
||||
byte z = (byte) y;
|
||||
return x + z;
|
||||
}
|
||||
|
||||
public long addC2L(long x, long y) {
|
||||
char z = (char) y;
|
||||
return x + z;
|
||||
}
|
||||
|
||||
public long addS2L(long x, long y) {
|
||||
short z = (short) y;
|
||||
return x + z;
|
||||
}
|
||||
|
||||
public int addB2S(int x, int y) {
|
||||
short a = (short) x;
|
||||
byte b = (byte) y;
|
||||
return a + b;
|
||||
}
|
||||
|
||||
public int addB2SShift(int x, int y) {
|
||||
short a = (short) x;
|
||||
byte b = (byte) y;
|
||||
return a + (b << 2);
|
||||
}
|
||||
|
||||
public int addB2I(int x, int y) {
|
||||
byte z = (byte) y;
|
||||
return x + z;
|
||||
}
|
||||
|
||||
public int addB2IShift(int x, int y) {
|
||||
byte z = (byte) y;
|
||||
return x + (z << 3);
|
||||
}
|
||||
|
||||
public int addS2I(int x, int y) {
|
||||
short z = (short) y;
|
||||
return x + z;
|
||||
}
|
||||
|
||||
public int addS2IShift(int x, int y) {
|
||||
short z = (short) y;
|
||||
return x + (z << 2);
|
||||
}
|
||||
|
||||
public int addC2I(int x, int y) {
|
||||
char z = (char) y;
|
||||
return x + z;
|
||||
}
|
||||
|
||||
public int addC2IShift(int x, int y) {
|
||||
char z = (char) y;
|
||||
return x + (z << 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mergeSignExtendIntoAdd() {
|
||||
predicateExist(new String[]{"addB2S", "addB2I", "addS2I", "addC2I"}, INT_VALUES, PRED_EXTEND_ADD_SHIFT);
|
||||
predicateExist(new String[]{"addB2L", "addC2L", "addI2L", "addS2L"}, LONG_VALUES, PRED_EXTEND_ADD_SHIFT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mergeSignExtendShiftIntoAdd() {
|
||||
predicateExist(new String[]{"addB2SShift", "addB2IShift", "addS2IShift", "addC2IShift"}, INT_VALUES, PRED_EXTEND_ADD_SHIFT);
|
||||
predicateExist(new String[]{"addB2LShift", "addC2LShift", "addI2LShift", "addS2LShift"}, LONG_VALUES, PRED_EXTEND_ADD_SHIFT);
|
||||
}
|
||||
|
||||
public long subI2L(long x, long y) {
|
||||
int z = (int) y;
|
||||
return x - z;
|
||||
}
|
||||
|
||||
public long subB2L(long x, long y) {
|
||||
byte z = (byte) y;
|
||||
return x - z;
|
||||
}
|
||||
|
||||
public long subC2L(long x, long y) {
|
||||
char z = (char) y;
|
||||
return x - z;
|
||||
}
|
||||
|
||||
public long subS2L(long x, long y) {
|
||||
short z = (short) y;
|
||||
return x - z;
|
||||
}
|
||||
|
||||
public int subB2S(int x, int y) {
|
||||
short a = (short) x;
|
||||
byte b = (byte) y;
|
||||
return a - b;
|
||||
}
|
||||
|
||||
public int subB2SShift(int x, int y) {
|
||||
short a = (short) x;
|
||||
byte b = (byte) y;
|
||||
return a - (b << 2);
|
||||
}
|
||||
|
||||
public int subB2I(int x, int y) {
|
||||
byte z = (byte) y;
|
||||
return x - z;
|
||||
}
|
||||
|
||||
public int subB2IShift(int x, int y) {
|
||||
byte z = (byte) y;
|
||||
return x - (z << 3);
|
||||
}
|
||||
|
||||
public int subS2I(int x, int y) {
|
||||
short z = (short) y;
|
||||
return x - z;
|
||||
}
|
||||
|
||||
public int subS2IShift(int x, int y) {
|
||||
short z = (short) y;
|
||||
return x - (z << 2);
|
||||
}
|
||||
|
||||
public int subC2I(int x, int y) {
|
||||
char z = (char) y;
|
||||
return x - z;
|
||||
}
|
||||
|
||||
public int subC2IShift(int x, int y) {
|
||||
char z = (char) y;
|
||||
return x - (z << 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mergeSignExtendShiftIntoSub() {
|
||||
predicateExist(new String[]{"subB2SShift", "subB2IShift", "subS2IShift", "subC2IShift"}, INT_VALUES, PRED_EXTEND_SUB_SHIFT);
|
||||
predicateExist(new String[]{"subB2LShift", "subC2LShift", "subI2LShift", "subS2LShift"}, LONG_VALUES, PRED_EXTEND_SUB_SHIFT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mergeSignExtendIntoSub() {
|
||||
predicateExist(new String[]{"subB2S", "subB2I", "subS2I", "subC2I"}, INT_VALUES, PRED_EXTEND_SUB_SHIFT);
|
||||
predicateExist(new String[]{"subB2L", "subC2L", "subI2L", "subS2L"}, LONG_VALUES, PRED_EXTEND_SUB_SHIFT);
|
||||
}
|
||||
}
|
@ -0,0 +1,314 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, Arm Limited. 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.LIRInstruction;
|
||||
import org.graalvm.compiler.lir.aarch64.AArch64ArithmeticOp;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class AArch64MergeNarrowWithAddSubTest extends AArch64MatchRuleTest {
|
||||
|
||||
private static final Predicate<LIRInstruction> PRED_EXTEND_ADD_SHIFT = op -> (op instanceof AArch64ArithmeticOp.ExtendedAddSubShiftOp && op.name().equals("ADD"));
|
||||
private static final Predicate<LIRInstruction> PRED_EXTEND_SUB_SHIFT = op -> (op instanceof AArch64ArithmeticOp.ExtendedAddSubShiftOp && op.name().equals("SUB"));
|
||||
|
||||
private static final Long[] LONG_VALUES = {-1L, 0L, 0x1234567812345678L, 0xFFFFFFFFL, 0x12L, 0x1234L, Long.MIN_VALUE, Long.MAX_VALUE};
|
||||
private static final Integer[] INT_VALUES = {-1, 0, 0x1234, 0x12345678, Integer.MIN_VALUE, Integer.MAX_VALUE};
|
||||
|
||||
private <T> void predicateExist(String[] testCases, T[] values, Predicate<LIRInstruction> predicate) {
|
||||
for (String t : testCases) {
|
||||
for (T value : values) {
|
||||
test(t, value, value);
|
||||
checkLIR(t, predicate, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int addIB(int x, int y) {
|
||||
return x + (y & 0xff);
|
||||
}
|
||||
|
||||
public int addIH(int x, int y) {
|
||||
return x + (y & 0xffff);
|
||||
}
|
||||
|
||||
public long addLB(long x, long y) {
|
||||
return x + (y & 0xff);
|
||||
}
|
||||
|
||||
public long addLH(long x, long y) {
|
||||
return x + (y & 0xffff);
|
||||
}
|
||||
|
||||
public long addLW(long x, long y) {
|
||||
return x + (y & 0xffffffffL);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mergeDowncastIntoAdd() {
|
||||
predicateExist(new String[]{"addIB", "addIH"}, INT_VALUES, PRED_EXTEND_ADD_SHIFT);
|
||||
predicateExist(new String[]{"addLB", "addLH", "addLW"}, LONG_VALUES, PRED_EXTEND_ADD_SHIFT);
|
||||
}
|
||||
|
||||
public int subIB(int x, int y) {
|
||||
return x - (y & 0xff);
|
||||
}
|
||||
|
||||
public int subIH(int x, int y) {
|
||||
return x - (y & 0xffff);
|
||||
}
|
||||
|
||||
public long subLB(long x, long y) {
|
||||
return x - (y & 0xff);
|
||||
}
|
||||
|
||||
public long subLH(long x, long y) {
|
||||
return x - (y & 0xffff);
|
||||
}
|
||||
|
||||
public long subLW(long x, long y) {
|
||||
return x - (y & 0xffffffffL);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mergeDowncastIntoSub() {
|
||||
predicateExist(new String[]{"subIB", "subIH"}, INT_VALUES, PRED_EXTEND_SUB_SHIFT);
|
||||
predicateExist(new String[]{"subLB", "subLH", "subLW"}, LONG_VALUES, PRED_EXTEND_SUB_SHIFT);
|
||||
}
|
||||
|
||||
public int addIBShift(int x, int y) {
|
||||
return x + ((y & 0xff) << 3);
|
||||
}
|
||||
|
||||
public int addIHShift(int x, int y) {
|
||||
return x + ((y & 0xffff) << 3);
|
||||
}
|
||||
|
||||
public long addLBShift(long x, long y) {
|
||||
return x + ((y & 0xffL) << 3);
|
||||
}
|
||||
|
||||
public long addLHShift(long x, long y) {
|
||||
return x + ((y & 0xffffL) << 3);
|
||||
}
|
||||
|
||||
public long addLWShift(long x, long y) {
|
||||
return x + ((y & 0xffffffffL) << 3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mergeShiftDowncastIntoAdd() {
|
||||
predicateExist(new String[]{"addIBShift", "addIHShift"}, INT_VALUES, PRED_EXTEND_ADD_SHIFT);
|
||||
predicateExist(new String[]{"addLBShift", "addLHShift", "addLWShift"}, LONG_VALUES, PRED_EXTEND_ADD_SHIFT);
|
||||
}
|
||||
|
||||
public int subIBShift(int x, int y) {
|
||||
return x - ((y & 0xff) << 3);
|
||||
}
|
||||
|
||||
public int subIHShift(int x, int y) {
|
||||
return x - ((y & 0xffff) << 3);
|
||||
}
|
||||
|
||||
public long subLBShift(long x, long y) {
|
||||
return x - ((y & 0xffL) << 3);
|
||||
}
|
||||
|
||||
public long subLHShift(long x, long y) {
|
||||
return x - ((y & 0xffffL) << 3);
|
||||
}
|
||||
|
||||
public long subLWShift(long x, long y) {
|
||||
return x - ((y & 0xffffffffL) << 3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mergeShiftDowncastIntoSub() {
|
||||
predicateExist(new String[]{"subIBShift", "subIHShift"}, INT_VALUES, PRED_EXTEND_SUB_SHIFT);
|
||||
predicateExist(new String[]{"subLBShift", "subLHShift", "subLWShift"}, LONG_VALUES, PRED_EXTEND_SUB_SHIFT);
|
||||
}
|
||||
|
||||
public int addIntExtractShort(int x, int y) {
|
||||
return x + ((y << 16) >> 16);
|
||||
}
|
||||
|
||||
public int addIntExtractByte(int x, int y) {
|
||||
return x + ((y << 24) >> 24);
|
||||
}
|
||||
|
||||
public long addLongExtractInt(long x, long y) {
|
||||
return x + ((y << 32) >> 32);
|
||||
}
|
||||
|
||||
public long addLongExtractShort(long x, long y) {
|
||||
return x + ((y << 48) >> 48);
|
||||
}
|
||||
|
||||
public long addLongExtractByte(long x, long y) {
|
||||
return x + ((y << 56) >> 56);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addSignExtractTest() {
|
||||
predicateExist(new String[]{"addIntExtractShort", "addIntExtractByte"}, INT_VALUES, PRED_EXTEND_ADD_SHIFT);
|
||||
predicateExist(new String[]{"addLongExtractInt", "addLongExtractShort", "addLongExtractByte"}, LONG_VALUES, PRED_EXTEND_ADD_SHIFT);
|
||||
}
|
||||
|
||||
public int addIntExtractShortByShift(int x, int y) {
|
||||
return x + (((y << 16) >> 16) << 3);
|
||||
}
|
||||
|
||||
public int addIntExtractByteByShift(int x, int y) {
|
||||
return x + (((y << 24) >> 24) << 3);
|
||||
}
|
||||
|
||||
public long addLongExtractIntByShift(long x, long y) {
|
||||
return x + (((y << 32) >> 32) << 3);
|
||||
}
|
||||
|
||||
public long addLongExtractShortByShift(long x, long y) {
|
||||
return x + (((y << 48) >> 48) << 3);
|
||||
}
|
||||
|
||||
public long addLongExtractByteByShift(long x, long y) {
|
||||
return x + (((y << 56) >> 56) << 3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addExtractByShiftTest() {
|
||||
predicateExist(new String[]{"addIntExtractShortByShift", "addIntExtractByteByShift"}, INT_VALUES, PRED_EXTEND_ADD_SHIFT);
|
||||
predicateExist(new String[]{"addLongExtractIntByShift", "addLongExtractShortByShift", "addLongExtractByteByShift"}, LONG_VALUES, PRED_EXTEND_ADD_SHIFT);
|
||||
}
|
||||
|
||||
public int addIntUnsignedExtractByte(int x, int y) {
|
||||
return x + ((y << 24) >>> 24);
|
||||
}
|
||||
|
||||
public long addLongUnsignedExtractByte(long x, long y) {
|
||||
return x + ((y << 56) >>> 56);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addUnsignedExtractTest() {
|
||||
predicateExist(new String[]{"addIntUnsignedExtractByte"}, INT_VALUES, PRED_EXTEND_ADD_SHIFT);
|
||||
predicateExist(new String[]{"addLongUnsignedExtractByte"}, LONG_VALUES, PRED_EXTEND_ADD_SHIFT);
|
||||
}
|
||||
|
||||
public int addIntUnsignedExtractByteByShift(int x, int y) {
|
||||
return x + (((y << 24) >>> 24) << 2);
|
||||
}
|
||||
|
||||
public long addLongUnsignedExtractByteByShift(long x, long y) {
|
||||
return x + (((y << 56) >>> 56) << 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addUnsignedExtractByShiftTest() {
|
||||
predicateExist(new String[]{"addIntUnsignedExtractByteByShift"}, INT_VALUES, PRED_EXTEND_ADD_SHIFT);
|
||||
predicateExist(new String[]{"addLongUnsignedExtractByteByShift"}, LONG_VALUES, PRED_EXTEND_ADD_SHIFT);
|
||||
}
|
||||
|
||||
public int subIntExtractShort(int x, int y) {
|
||||
return x - ((y << 16) >> 16);
|
||||
}
|
||||
|
||||
public int subIntExtractByte(int x, int y) {
|
||||
return x - ((y << 24) >> 24);
|
||||
}
|
||||
|
||||
public long subLongExtractInt(long x, long y) {
|
||||
return x - ((y << 32) >> 32);
|
||||
}
|
||||
|
||||
public long subLongExtractShort(long x, long y) {
|
||||
return x - ((y << 48) >> 48);
|
||||
}
|
||||
|
||||
public long subLongExtractByte(long x, long y) {
|
||||
return x - ((y << 56) >> 56);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void subExtractTest() {
|
||||
predicateExist(new String[]{"subIntExtractShort", "subIntExtractByte"}, INT_VALUES, PRED_EXTEND_SUB_SHIFT);
|
||||
predicateExist(new String[]{"subLongExtractInt", "subLongExtractShort", "subLongExtractByte"}, LONG_VALUES, PRED_EXTEND_SUB_SHIFT);
|
||||
}
|
||||
|
||||
public int subIntExtractShortByShift(int x, int y) {
|
||||
return x - (((y << 16) >> 16) << 3);
|
||||
}
|
||||
|
||||
public int subIntExtractByteByShift(int x, int y) {
|
||||
return x - (((y << 24) >> 24) << 3);
|
||||
}
|
||||
|
||||
public long subLongExtractIntByShift(long x, long y) {
|
||||
return x - (((y << 32) >> 32) << 3);
|
||||
}
|
||||
|
||||
public long subLongExtractShortByShift(long x, long y) {
|
||||
return x - (((y << 48) >> 48) << 3);
|
||||
}
|
||||
|
||||
public long subLongExtractByteByShift(long x, long y) {
|
||||
return x - (((y << 56) >> 56) << 3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void subExtractByShiftTest() {
|
||||
predicateExist(new String[]{"subIntExtractShortByShift", "subIntExtractByteByShift"}, INT_VALUES, PRED_EXTEND_SUB_SHIFT);
|
||||
predicateExist(new String[]{"subLongExtractIntByShift", "subLongExtractShortByShift", "subLongExtractByteByShift"}, LONG_VALUES, PRED_EXTEND_SUB_SHIFT);
|
||||
}
|
||||
|
||||
public int subIntUnsignedExtractByte(int x, int y) {
|
||||
return x - ((y << 24) >>> 24);
|
||||
}
|
||||
|
||||
public long subLongUnsignedExtractByte(long x, long y) {
|
||||
return x - ((y << 56) >>> 56);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void subUnsignedExtractTest() {
|
||||
predicateExist(new String[]{"subIntUnsignedExtractByte"}, INT_VALUES, PRED_EXTEND_SUB_SHIFT);
|
||||
predicateExist(new String[]{"subLongUnsignedExtractByte"}, LONG_VALUES, PRED_EXTEND_SUB_SHIFT);
|
||||
}
|
||||
|
||||
public int subIntUnsignedExtractByteByShift(int x, int y) {
|
||||
return x - (((y << 24) >>> 24) << 1);
|
||||
}
|
||||
|
||||
public long subLongUnsignedExtractByteByShift(long x, long y) {
|
||||
return x - (((y << 56) >>> 56) << 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void subUnsignedExtractByShiftTest() {
|
||||
predicateExist(new String[]{"subIntUnsignedExtractByteByShift"}, INT_VALUES, PRED_EXTEND_SUB_SHIFT);
|
||||
predicateExist(new String[]{"subLongUnsignedExtractByteByShift"}, LONG_VALUES, PRED_EXTEND_SUB_SHIFT);
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2020, 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
|
||||
@ -62,7 +62,7 @@ public class AArch64TestBitAndBranchTest extends LIRTest {
|
||||
|
||||
public static long testBit42Snippet(long a, long b, long c) {
|
||||
if ((a & (1L << 42)) == 0) {
|
||||
return b;
|
||||
return b + c;
|
||||
} else {
|
||||
return c;
|
||||
}
|
||||
|
@ -0,0 +1,194 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, Red Hat Inc. 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.aarch64.AArch64Kind;
|
||||
import org.graalvm.compiler.core.test.MatchRuleTest;
|
||||
import org.graalvm.compiler.lir.LIRInstruction;
|
||||
import org.graalvm.compiler.lir.aarch64.AArch64Move;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import static org.junit.Assume.assumeTrue;
|
||||
|
||||
public class AArch64VolatileAccessesTest extends MatchRuleTest {
|
||||
private static volatile byte volatileByteField;
|
||||
private static volatile short volatileShortField;
|
||||
private static volatile int volatileIntField;
|
||||
private static volatile long volatileLongField;
|
||||
private static volatile float volatileFloatField;
|
||||
private static volatile double volatileDoubleField;
|
||||
|
||||
private static Predicate<LIRInstruction> storePredicate(AArch64Kind kind) {
|
||||
return op -> (op instanceof AArch64Move.VolatileStoreOp && ((AArch64Move.VolatileStoreOp) op).getKind() == kind);
|
||||
}
|
||||
|
||||
private static Predicate<LIRInstruction> loadPredicate(AArch64Kind kind) {
|
||||
return op -> (op instanceof AArch64Move.VolatileLoadOp && ((AArch64Move.VolatileLoadOp) op).getKind() == kind);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void checkAArch64() {
|
||||
assumeTrue("skipping AArch64 specific test", getTarget().arch instanceof AArch64);
|
||||
}
|
||||
|
||||
public static byte volatileByteFieldLoad() {
|
||||
return volatileByteField;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test01() {
|
||||
checkLIR("volatileByteFieldLoad", loadPredicate(AArch64Kind.BYTE), 1);
|
||||
volatileByteField = 42;
|
||||
test("volatileByteFieldLoad");
|
||||
}
|
||||
|
||||
public static short volatileShortFieldLoad() {
|
||||
return volatileShortField;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test02() {
|
||||
checkLIR("volatileShortFieldLoad", loadPredicate(AArch64Kind.WORD), 1);
|
||||
volatileShortField = 42;
|
||||
test("volatileShortFieldLoad");
|
||||
}
|
||||
|
||||
public static int volatileIntFieldLoad() {
|
||||
return volatileIntField;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test03() {
|
||||
checkLIR("volatileIntFieldLoad", loadPredicate(AArch64Kind.DWORD), 1);
|
||||
volatileIntField = 42;
|
||||
test("volatileIntFieldLoad");
|
||||
}
|
||||
|
||||
public static long volatileLongFieldLoad() {
|
||||
return volatileLongField;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test04() {
|
||||
checkLIR("volatileLongFieldLoad", loadPredicate(AArch64Kind.QWORD), 1);
|
||||
volatileLongField = 42;
|
||||
test("volatileLongFieldLoad");
|
||||
}
|
||||
|
||||
public static float volatileFloatFieldLoad() {
|
||||
return volatileFloatField;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test05() {
|
||||
checkLIR("volatileFloatFieldLoad", loadPredicate(AArch64Kind.SINGLE), 1);
|
||||
volatileFloatField = 42;
|
||||
test("volatileFloatFieldLoad");
|
||||
}
|
||||
|
||||
public static double volatileDoubleFieldLoad() {
|
||||
return volatileDoubleField;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test06() {
|
||||
checkLIR("volatileDoubleFieldLoad", loadPredicate(AArch64Kind.DOUBLE), 1);
|
||||
volatileDoubleField = 42;
|
||||
test("volatileDoubleFieldLoad");
|
||||
}
|
||||
|
||||
public static void volatileByteFieldStore(byte v) {
|
||||
volatileByteField = v;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test07() {
|
||||
checkLIR("volatileByteFieldStore", storePredicate(AArch64Kind.BYTE), 1);
|
||||
executeActual(getResolvedJavaMethod("volatileByteFieldStore"), (byte) 0x42);
|
||||
Assert.assertEquals(volatileByteField, 0x42);
|
||||
}
|
||||
|
||||
public static void volatileShortFieldStore(short v) {
|
||||
volatileShortField = v;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test08() {
|
||||
checkLIR("volatileShortFieldStore", storePredicate(AArch64Kind.WORD), 1);
|
||||
executeActual(getResolvedJavaMethod("volatileShortFieldStore"), (short) 0x42);
|
||||
Assert.assertEquals(volatileShortField, 0x42);
|
||||
}
|
||||
|
||||
public static void volatileIntFieldStore(int v) {
|
||||
volatileIntField = v;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test09() {
|
||||
checkLIR("volatileIntFieldStore", storePredicate(AArch64Kind.DWORD), 1);
|
||||
executeActual(getResolvedJavaMethod("volatileIntFieldStore"), 0x42);
|
||||
Assert.assertEquals(volatileIntField, 0x42);
|
||||
}
|
||||
|
||||
public static void volatileLongFieldStore(int v) {
|
||||
volatileLongField = v;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test10() {
|
||||
checkLIR("volatileLongFieldStore", storePredicate(AArch64Kind.QWORD), 1);
|
||||
executeActual(getResolvedJavaMethod("volatileLongFieldStore"), 0x42);
|
||||
Assert.assertEquals(volatileLongField, 0x42);
|
||||
}
|
||||
|
||||
public static void volatileFloatFieldStore(float v) {
|
||||
volatileFloatField = v;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test11() {
|
||||
checkLIR("volatileFloatFieldStore", storePredicate(AArch64Kind.SINGLE), 1);
|
||||
executeActual(getResolvedJavaMethod("volatileFloatFieldStore"), (float) 0x42);
|
||||
Assert.assertEquals(volatileFloatField, 0x42, 0);
|
||||
}
|
||||
|
||||
public static void volatileDoubleFieldStore(double v) {
|
||||
volatileDoubleField = v;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test12() {
|
||||
checkLIR("volatileDoubleFieldStore", storePredicate(AArch64Kind.DOUBLE), 1);
|
||||
executeActual(getResolvedJavaMethod("volatileDoubleFieldStore"), (double) 0x42);
|
||||
Assert.assertEquals(volatileDoubleField, 0x42, 0);
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2020, 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
|
||||
@ -46,6 +46,7 @@ import org.graalvm.compiler.lir.aarch64.AArch64AddressValue;
|
||||
import org.graalvm.compiler.lir.aarch64.AArch64ArithmeticLIRGeneratorTool;
|
||||
import org.graalvm.compiler.lir.aarch64.AArch64ArithmeticOp;
|
||||
import org.graalvm.compiler.lir.aarch64.AArch64BitManipulationOp;
|
||||
import org.graalvm.compiler.lir.aarch64.AArch64Move;
|
||||
import org.graalvm.compiler.lir.aarch64.AArch64Move.LoadOp;
|
||||
import org.graalvm.compiler.lir.aarch64.AArch64Move.StoreConstantOp;
|
||||
import org.graalvm.compiler.lir.aarch64.AArch64Move.StoreOp;
|
||||
@ -237,7 +238,7 @@ public class AArch64ArithmeticLIRGenerator extends ArithmeticLIRGenerator implem
|
||||
result = getLIRGen().newVariable(LIRKind.combine(c));
|
||||
} else {
|
||||
assert a.getPlatformKind() == c.getPlatformKind();
|
||||
if (op == AArch64ArithmeticOp.FADD) {
|
||||
if (op == AArch64ArithmeticOp.FMADD) {
|
||||
// For floating-point Math.fma intrinsic.
|
||||
assert a.getPlatformKind() == AArch64Kind.SINGLE || a.getPlatformKind() == AArch64Kind.DOUBLE;
|
||||
} else {
|
||||
@ -506,6 +507,14 @@ public class AArch64ArithmeticLIRGenerator extends ArithmeticLIRGenerator implem
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Variable emitVolatileLoad(LIRKind kind, Value address, LIRFrameState state) {
|
||||
AllocatableValue loadAddress = asAllocatable(address);
|
||||
Variable result = getLIRGen().newVariable(getLIRGen().toRegisterKind(kind));
|
||||
getLIRGen().append(new AArch64Move.VolatileLoadOp((AArch64Kind) kind.getPlatformKind(), result, loadAddress, state));
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void emitStore(ValueKind<?> lirKind, Value address, Value inputVal, LIRFrameState state) {
|
||||
AArch64AddressValue storeAddress = getLIRGen().asAddressValue(address);
|
||||
@ -523,6 +532,14 @@ public class AArch64ArithmeticLIRGenerator extends ArithmeticLIRGenerator implem
|
||||
getLIRGen().append(new StoreOp(kind, storeAddress, input, state));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void emitVolatileStore(ValueKind<?> lirKind, Value addressVal, Value inputVal, LIRFrameState state) {
|
||||
AArch64Kind kind = (AArch64Kind) lirKind.getPlatformKind();
|
||||
AllocatableValue input = asAllocatable(inputVal);
|
||||
AllocatableValue address = asAllocatable(addressVal);
|
||||
getLIRGen().append(new AArch64Move.VolatileStoreOp(kind, address, input, state));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value emitRound(Value value, RoundingMode mode) {
|
||||
AArch64ArithmeticOp op;
|
||||
|
@ -141,6 +141,22 @@ public class AArch64NodeMatchRules extends NodeMatchRules {
|
||||
}
|
||||
}
|
||||
|
||||
private static ExtendType getSignExtendType(int fromBits) {
|
||||
switch (fromBits) {
|
||||
case Byte.SIZE:
|
||||
return ExtendType.SXTB;
|
||||
case Short.SIZE:
|
||||
return ExtendType.SXTH;
|
||||
case Integer.SIZE:
|
||||
return ExtendType.SXTW;
|
||||
case Long.SIZE:
|
||||
return ExtendType.SXTX;
|
||||
default:
|
||||
GraalError.shouldNotReachHere("extended from " + fromBits + "bits is not supported!");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private AllocatableValue moveSp(AllocatableValue value) {
|
||||
return getLIRGeneratorTool().moveSp(value);
|
||||
}
|
||||
@ -190,7 +206,83 @@ public class AArch64NodeMatchRules extends NodeMatchRules {
|
||||
}
|
||||
|
||||
private static boolean isNarrowingLongToInt(NarrowNode narrow) {
|
||||
return narrow.getInputBits() == 64 && narrow.getResultBits() == 32;
|
||||
return narrow.getInputBits() == Long.SIZE && narrow.getResultBits() == Integer.SIZE;
|
||||
}
|
||||
|
||||
private ComplexMatchResult emitExtendedAddSubShift(BinaryNode op, ValueNode x, ValueNode y, ExtendType extType, int shiftAmt) {
|
||||
assert op instanceof AddNode || op instanceof SubNode;
|
||||
return builder -> {
|
||||
AllocatableValue src1 = moveSp(gen.asAllocatable(operand(x)));
|
||||
AllocatableValue src2 = moveSp(gen.asAllocatable(operand(y)));
|
||||
Variable result = gen.newVariable(LIRKind.combine(operand(x), operand(y)));
|
||||
AArch64ArithmeticOp arithmeticOp = op instanceof AddNode ? AArch64ArithmeticOp.ADD : AArch64ArithmeticOp.SUB;
|
||||
gen.append(new AArch64ArithmeticOp.ExtendedAddSubShiftOp(arithmeticOp, result, src1, src2, extType, shiftAmt));
|
||||
return result;
|
||||
};
|
||||
}
|
||||
|
||||
@MatchRule("(Add=op x (LeftShift (SignExtend=ext y) Constant=lshift))")
|
||||
@MatchRule("(Sub=op x (LeftShift (SignExtend=ext y) Constant=lshift))")
|
||||
@MatchRule("(Add=op x (LeftShift (ZeroExtend=ext y) Constant=lshift))")
|
||||
@MatchRule("(Sub=op x (LeftShift (ZeroExtend=ext y) Constant=lshift))")
|
||||
public ComplexMatchResult mergeSignExtendByShiftIntoAddSub(BinaryNode op, UnaryNode ext, ValueNode x, ValueNode y, ConstantNode lshift) {
|
||||
assert lshift.getStackKind().isNumericInteger();
|
||||
int shiftAmt = lshift.asJavaConstant().asInt();
|
||||
if (shiftAmt > 4 || shiftAmt < 0) {
|
||||
return null;
|
||||
}
|
||||
ExtendType extType;
|
||||
if (ext instanceof SignExtendNode) {
|
||||
extType = getSignExtendType(((SignExtendNode) ext).getInputBits());
|
||||
} else {
|
||||
extType = getZeroExtendType(((ZeroExtendNode) ext).getInputBits());
|
||||
}
|
||||
return emitExtendedAddSubShift(op, x, y, extType, shiftAmt);
|
||||
}
|
||||
|
||||
@MatchRule("(Add=op x (LeftShift (And y Constant=constant) Constant=lshift))")
|
||||
@MatchRule("(Sub=op x (LeftShift (And y Constant=constant) Constant=lshift))")
|
||||
public ComplexMatchResult mergeShiftDowncastIntoAddSub(BinaryNode op, ValueNode x, ValueNode y, ConstantNode constant, ConstantNode lshift) {
|
||||
assert lshift.getStackKind().isNumericInteger();
|
||||
assert constant.getStackKind().isNumericInteger();
|
||||
int shiftAmt = lshift.asJavaConstant().asInt();
|
||||
long mask = constant.asJavaConstant().asLong();
|
||||
if (shiftAmt > 4 || shiftAmt < 0) {
|
||||
return null;
|
||||
}
|
||||
if (mask != 0xff && mask != 0xffff && mask != 0xffffffffL) {
|
||||
return null;
|
||||
}
|
||||
ExtendType extType = getZeroExtendType(Long.toBinaryString(mask).length());
|
||||
return emitExtendedAddSubShift(op, x, y, extType, shiftAmt);
|
||||
}
|
||||
|
||||
@MatchRule("(Add=op x (RightShift (LeftShift y Constant=shiftConst) Constant=shiftConst))")
|
||||
@MatchRule("(Sub=op x (RightShift (LeftShift y Constant=shiftConst) Constant=shiftConst))")
|
||||
public ComplexMatchResult mergePairShiftIntoAddSub(BinaryNode op, ValueNode x, ValueNode y, ConstantNode shiftConst) {
|
||||
assert shiftConst.getStackKind().isNumericInteger();
|
||||
int shift = shiftConst.asJavaConstant().asInt();
|
||||
if (shift != 16 && shift != 24 && shift != 32 && shift != 48 && shift != 56) {
|
||||
return null;
|
||||
}
|
||||
int extractBits = shift >= 32 ? Long.SIZE - shift : Integer.SIZE - shift;
|
||||
return emitExtendedAddSubShift(op, x, y, getSignExtendType(extractBits), 0);
|
||||
}
|
||||
|
||||
@MatchRule("(Add=op x (LeftShift (RightShift (LeftShift y Constant=shiftConst) Constant=shiftConst) Constant=lshift))")
|
||||
@MatchRule("(Sub=op x (LeftShift (RightShift (LeftShift y Constant=shiftConst) Constant=shiftConst) Constant=lshift))")
|
||||
public ComplexMatchResult mergeShiftedPairShiftIntoAddSub(BinaryNode op, ValueNode x, ValueNode y, ConstantNode shiftConst, ConstantNode lshift) {
|
||||
assert shiftConst.getStackKind().isNumericInteger();
|
||||
int shift = shiftConst.asJavaConstant().asInt();
|
||||
int shiftAmt = lshift.asJavaConstant().asInt();
|
||||
if (shiftAmt > 4 || shiftAmt < 0) {
|
||||
return null;
|
||||
}
|
||||
if (shift != 16 && shift != 24 && shift != 32 && shift != 48 && shift != 56) {
|
||||
return null;
|
||||
}
|
||||
int extractBits = shift >= 32 ? Long.SIZE - shift : Integer.SIZE - shift;
|
||||
return emitExtendedAddSubShift(op, x, y, getSignExtendType(extractBits), shiftAmt);
|
||||
}
|
||||
|
||||
@MatchRule("(AArch64PointerAdd=addP base ZeroExtend)")
|
||||
@ -225,7 +317,7 @@ public class AArch64NodeMatchRules extends NodeMatchRules {
|
||||
LIRKind kind = LIRKind.combineDerived(gen.getLIRKind(addP.stamp(NodeView.DEFAULT)),
|
||||
baseReference, null);
|
||||
Variable result = gen.newVariable(kind);
|
||||
gen.append(new AArch64ArithmeticOp.ExtendedAddShiftOp(result, x, moveSp(y),
|
||||
gen.append(new AArch64ArithmeticOp.ExtendedAddSubShiftOp(AArch64ArithmeticOp.ADD, result, x, moveSp(y),
|
||||
extendType, shiftNum));
|
||||
return result;
|
||||
};
|
||||
@ -469,6 +561,32 @@ public class AArch64NodeMatchRules extends NodeMatchRules {
|
||||
resultKind, op, commutative, operand(src2), operand(src1));
|
||||
}
|
||||
|
||||
@MatchRule("(Add=op x (And y Constant=constant))")
|
||||
@MatchRule("(Sub=op x (And y Constant=constant))")
|
||||
public ComplexMatchResult mergeDowncastIntoAddSub(BinaryNode op, ValueNode x, ValueNode y, ConstantNode constant) {
|
||||
assert constant.getStackKind().isNumericInteger();
|
||||
long mask = constant.asJavaConstant().asLong();
|
||||
if (mask != 0xff && mask != 0xffff && mask != 0xffffffffL) {
|
||||
return null;
|
||||
}
|
||||
ExtendType extType = getZeroExtendType(Long.toBinaryString(mask).length());
|
||||
return emitExtendedAddSubShift(op, x, y, extType, 0);
|
||||
}
|
||||
|
||||
@MatchRule("(Add=op x (SignExtend=ext y))")
|
||||
@MatchRule("(Sub=op x (SignExtend=ext y))")
|
||||
@MatchRule("(Add=op x (ZeroExtend=ext y))")
|
||||
@MatchRule("(Sub=op x (ZeroExtend=ext y))")
|
||||
public ComplexMatchResult mergeSignExtendIntoAddSub(BinaryNode op, UnaryNode ext, ValueNode x, ValueNode y) {
|
||||
ExtendType extType;
|
||||
if (ext instanceof SignExtendNode) {
|
||||
extType = getSignExtendType(((SignExtendNode) ext).getInputBits());
|
||||
} else {
|
||||
extType = getZeroExtendType(((ZeroExtendNode) ext).getInputBits());
|
||||
}
|
||||
return emitExtendedAddSubShift(op, x, y, extType, 0);
|
||||
}
|
||||
|
||||
@MatchRule("(Negate=unary (Narrow=narrow value))")
|
||||
@MatchRule("(Not=unary (Narrow=narrow value))")
|
||||
public ComplexMatchResult elideL2IForUnary(UnaryNode unary, NarrowNode narrow) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, Red Hat Inc. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -31,6 +31,7 @@ import org.graalvm.compiler.nodes.StructuredGraph;
|
||||
import org.graalvm.compiler.nodes.calc.SignExtendNode;
|
||||
import org.graalvm.compiler.nodes.calc.ZeroExtendNode;
|
||||
import org.graalvm.compiler.nodes.memory.ReadNode;
|
||||
import org.graalvm.compiler.nodes.memory.VolatileReadNode;
|
||||
import org.graalvm.compiler.phases.Phase;
|
||||
|
||||
/**
|
||||
@ -46,7 +47,7 @@ public class AArch64ReadReplacementPhase extends Phase {
|
||||
if (node instanceof AArch64ReadNode) {
|
||||
continue;
|
||||
}
|
||||
if (node instanceof ReadNode) {
|
||||
if (node instanceof ReadNode && !(node instanceof VolatileReadNode)) {
|
||||
ReadNode readNode = (ReadNode) node;
|
||||
if (readNode.hasExactlyOneUsage()) {
|
||||
Node usage = readNode.usages().first();
|
||||
|
@ -1177,6 +1177,16 @@ public class AMD64ArithmeticLIRGenerator extends ArithmeticLIRGenerator implemen
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Variable emitVolatileLoad(LIRKind kind, Value address, LIRFrameState state) {
|
||||
throw GraalError.shouldNotReachHere();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void emitVolatileStore(ValueKind<?> kind, Value address, Value input, LIRFrameState state) {
|
||||
throw GraalError.shouldNotReachHere();
|
||||
}
|
||||
|
||||
protected void emitStoreConst(AMD64Kind kind, AMD64AddressValue address, ConstantValue value, LIRFrameState state) {
|
||||
Constant c = value.getConstant();
|
||||
if (JavaConstant.isNull(c)) {
|
||||
|
@ -107,7 +107,7 @@ import org.graalvm.compiler.lir.amd64.AMD64ZeroMemoryOp;
|
||||
import org.graalvm.compiler.lir.amd64.vector.AMD64VectorCompareOp;
|
||||
import org.graalvm.compiler.lir.gen.LIRGenerationResult;
|
||||
import org.graalvm.compiler.lir.gen.LIRGenerator;
|
||||
import org.graalvm.compiler.lir.hashing.Hasher;
|
||||
import org.graalvm.compiler.lir.hashing.IntHasher;
|
||||
import org.graalvm.compiler.phases.util.Providers;
|
||||
|
||||
import jdk.vm.ci.amd64.AMD64;
|
||||
@ -317,8 +317,9 @@ public abstract class AMD64LIRGenerator extends LIRGenerator {
|
||||
@Override
|
||||
public void emitCompareBranch(PlatformKind cmpKind, Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef trueLabel, LabelRef falseLabel, double trueLabelProbability) {
|
||||
if (cmpKind == AMD64Kind.SINGLE || cmpKind == AMD64Kind.DOUBLE) {
|
||||
boolean isSelfEqualsCheck = cond == Condition.EQ && !unorderedIsTrue && left.equals(right);
|
||||
Condition finalCondition = emitCompare(cmpKind, left, right, cond);
|
||||
append(new FloatBranchOp(finalCondition, unorderedIsTrue, trueLabel, falseLabel, trueLabelProbability));
|
||||
append(new FloatBranchOp(finalCondition, unorderedIsTrue, trueLabel, falseLabel, trueLabelProbability, isSelfEqualsCheck));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -459,10 +460,15 @@ public abstract class AMD64LIRGenerator extends LIRGenerator {
|
||||
finalCondition = emitCompare(cmpKind, left, right, cond);
|
||||
}
|
||||
|
||||
return emitCondMoveOp(finalCondition, finalTrueValue, finalFalseValue, isFloatComparison, unorderedIsTrue);
|
||||
boolean isSelfEqualsCheck = isFloatComparison && finalCondition == Condition.EQ && left.equals(right);
|
||||
return emitCondMoveOp(finalCondition, finalTrueValue, finalFalseValue, isFloatComparison, unorderedIsTrue, isSelfEqualsCheck);
|
||||
}
|
||||
|
||||
private Variable emitCondMoveOp(Condition condition, Value trueValue, Value falseValue, boolean isFloatComparison, boolean unorderedIsTrue) {
|
||||
return emitCondMoveOp(condition, trueValue, falseValue, isFloatComparison, unorderedIsTrue, false);
|
||||
}
|
||||
|
||||
private Variable emitCondMoveOp(Condition condition, Value trueValue, Value falseValue, boolean isFloatComparison, boolean unorderedIsTrue, boolean isSelfEqualsCheck) {
|
||||
boolean isParityCheckNecessary = isFloatComparison && unorderedIsTrue != AMD64ControlFlow.trueOnUnordered(condition);
|
||||
Variable result = newVariable(trueValue.getValueKind());
|
||||
if (!isParityCheckNecessary && isIntConstant(trueValue, 1) && isIntConstant(falseValue, 0)) {
|
||||
@ -485,7 +491,7 @@ public abstract class AMD64LIRGenerator extends LIRGenerator {
|
||||
append(new CondSetOp(result, condition.negate()));
|
||||
}
|
||||
} else if (isFloatComparison) {
|
||||
append(new FloatCondMoveOp(result, condition, unorderedIsTrue, load(trueValue), load(falseValue)));
|
||||
append(new FloatCondMoveOp(result, condition, unorderedIsTrue, load(trueValue), load(falseValue), isSelfEqualsCheck));
|
||||
} else {
|
||||
append(new CondMoveOp(result, condition, load(trueValue), loadNonConst(falseValue)));
|
||||
}
|
||||
@ -686,16 +692,31 @@ public abstract class AMD64LIRGenerator extends LIRGenerator {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Optional<Hasher> hasherFor(JavaConstant[] keyConstants, double minDensity) {
|
||||
return Hasher.forKeys(keyConstants, minDensity);
|
||||
protected Optional<IntHasher> hasherFor(JavaConstant[] keyConstants, double minDensity) {
|
||||
int[] keys = new int[keyConstants.length];
|
||||
for (int i = 0; i < keyConstants.length; i++) {
|
||||
keys[i] = keyConstants[i].asInt();
|
||||
}
|
||||
return IntHasher.forKeys(keys);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void emitHashTableSwitch(Hasher hasher, JavaConstant[] keys, LabelRef defaultTarget, LabelRef[] targets, Value value) {
|
||||
Value index = hasher.hash(value, arithmeticLIRGen);
|
||||
protected void emitHashTableSwitch(IntHasher hasher, JavaConstant[] keys, LabelRef defaultTarget, LabelRef[] targets, Value value) {
|
||||
Value hash = value;
|
||||
if (hasher.factor > 1) {
|
||||
Value factor = emitJavaConstant(JavaConstant.forShort(hasher.factor));
|
||||
hash = arithmeticLIRGen.emitMul(hash, factor, false);
|
||||
}
|
||||
if (hasher.shift > 0) {
|
||||
Value shift = emitJavaConstant(JavaConstant.forByte(hasher.shift));
|
||||
hash = arithmeticLIRGen.emitShr(hash, shift);
|
||||
}
|
||||
Value cardinalityAnd = emitJavaConstant(JavaConstant.forInt(hasher.cardinality - 1));
|
||||
hash = arithmeticLIRGen.emitAnd(hash, cardinalityAnd);
|
||||
|
||||
Variable scratch = newVariable(LIRKind.value(target().arch.getWordKind()));
|
||||
Variable entryScratch = newVariable(LIRKind.value(target().arch.getWordKind()));
|
||||
append(new HashTableSwitchOp(keys, defaultTarget, targets, value, index, scratch, entryScratch));
|
||||
append(new HashTableSwitchOp(keys, defaultTarget, targets, value, hash, scratch, entryScratch));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (c) 2020, 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.debug.CompilationListener;
|
||||
import org.graalvm.compiler.debug.DebugContext.CompilerPhaseScope;
|
||||
|
||||
import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||
|
||||
/**
|
||||
* Connects a {@link CompilationListener} to a {@link CompilerProfiler}.
|
||||
*/
|
||||
public class CompilationListenerProfiler implements CompilationListener {
|
||||
private final int compileId;
|
||||
private final CompilerProfiler profiler;
|
||||
|
||||
/**
|
||||
* Creates a compilation listener that passes events for a specific compilation identified by
|
||||
* {@code compileId} onto {@code profiler}.
|
||||
*/
|
||||
public CompilationListenerProfiler(CompilerProfiler profiler, int compileId) {
|
||||
this.profiler = profiler;
|
||||
this.compileId = compileId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyInlining(ResolvedJavaMethod caller, ResolvedJavaMethod callee, boolean succeeded, CharSequence message, int bci) {
|
||||
profiler.notifyCompilerInlingEvent(compileId, caller, callee, succeeded, message.toString(), bci);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompilerPhaseScope enterPhase(CharSequence name, int nesting) {
|
||||
long start = profiler.getTicks();
|
||||
return new CompilerPhaseScope() {
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
profiler.notifyCompilerPhaseEvent(compileId, start, name.toString(), nesting);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
63
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/CompilerProfiler.java
Normal file
63
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/CompilerProfiler.java
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2020, 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 jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||
|
||||
/**
|
||||
* A profiling service that consumes compilation related events. The Java Flight Recorder (JFR) is
|
||||
* an example of such a service that can be exposed via this interface.
|
||||
*/
|
||||
public interface CompilerProfiler {
|
||||
|
||||
/**
|
||||
* Get current value of the profiler's time counter.
|
||||
*
|
||||
* @return the number of profile-defined time units that have elapsed
|
||||
*/
|
||||
long getTicks();
|
||||
|
||||
/**
|
||||
* Notifies JFR when a compiler phase ends.
|
||||
*
|
||||
* @param compileId current computation unit id
|
||||
* @param startTime when the phase started
|
||||
* @param name name of the phase
|
||||
* @param nestingLevel how many ancestor phases there are of the phase
|
||||
*/
|
||||
void notifyCompilerPhaseEvent(int compileId, long startTime, String name, int nestingLevel);
|
||||
|
||||
/**
|
||||
* Notifies JFR when the compiler considers inlining {@code callee} into {@code caller}.
|
||||
*
|
||||
* @param compileId current computation unit id
|
||||
* @param caller caller method
|
||||
* @param callee callee method considered for inlining into {@code caller}
|
||||
* @param succeeded true if {@code callee} was inlined into {@code caller}
|
||||
* @param message extra information about inlining decision
|
||||
* @param bci byte code index of call site
|
||||
*/
|
||||
void notifyCompilerInlingEvent(int compileId, ResolvedJavaMethod caller, ResolvedJavaMethod callee, boolean succeeded, String message, int bci);
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2009, 2020, 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
|
||||
@ -271,6 +271,6 @@ public final class GraalOptions {
|
||||
@Option(help = "Alignment in bytes for loop header blocks.", type = OptionType.Expert)
|
||||
public static final OptionKey<Integer> LoopHeaderAlignment = new OptionKey<>(16);
|
||||
|
||||
@Option(help = "Do not include membars for volatile accesses until the end of optimizations.", type = OptionType.Expert)
|
||||
public static final OptionKey<Boolean> LateMembars = new OptionKey<>(true);
|
||||
@Option(help = "String.indexOf invocations will be evaluated at compile time if the receiver is a constant and its length is lower than this value.", type = OptionType.Expert)
|
||||
public static final OptionKey<Integer> StringIndexOfLimit = new OptionKey<>(4096);
|
||||
}
|
||||
|
@ -136,6 +136,14 @@ public class NumUtil {
|
||||
return number / mod * mod;
|
||||
}
|
||||
|
||||
public static int divideAndRoundUp(int number, int divisor) {
|
||||
return (number + divisor - 1) / divisor;
|
||||
}
|
||||
|
||||
public static long divideAndRoundUp(long number, long divisor) {
|
||||
return (number + divisor - 1L) / divisor;
|
||||
}
|
||||
|
||||
public static int log2Ceil(int val) {
|
||||
int x = 1;
|
||||
int log2 = 0;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2009, 2020, 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
|
||||
@ -533,6 +533,130 @@ public enum Condition {
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean in(Condition needle, Condition... haystack) {
|
||||
for (Condition c : haystack) {
|
||||
if (c == needle) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this condition and {@code other} will never both return true for the same
|
||||
* arguments. This means that tests using these conditions can be safely reordered.
|
||||
*/
|
||||
public boolean trueIsDisjoint(Condition other) {
|
||||
if (other == this) {
|
||||
return false;
|
||||
}
|
||||
switch (this) {
|
||||
case EQ: {
|
||||
// 0 EQ 0 is not disjoint from 0 LE 0
|
||||
// 0 EQ 0 is not disjoint from 0 GE 0
|
||||
// 0 EQ 0 is not disjoint from 0 AE 0
|
||||
// 0 EQ 0 is not disjoint from 0 BE 0
|
||||
return in(other, NE, LT, GT, AT, BT);
|
||||
}
|
||||
case NE: {
|
||||
// 0 NE 1 is not disjoint from 0 LT 1
|
||||
// 0 NE 1 is not disjoint from 0 LE 1
|
||||
// 0 NE -1 is not disjoint from 0 GT -1
|
||||
// 0 NE -1 is not disjoint from 0 GE -1
|
||||
// 1 NE 0 is not disjoint from 1 AE 0
|
||||
// 0 NE 1 is not disjoint from 0 BE 1
|
||||
// 1 NE 0 is not disjoint from 1 AT 0
|
||||
// 0 NE 1 is not disjoint from 0 BT 1
|
||||
return other == EQ;
|
||||
}
|
||||
case LT: {
|
||||
// 0 LT 1 is not disjoint from 0 NE 1
|
||||
// 0 LT 1 is not disjoint from 0 LE 1
|
||||
// -1 LT 0 is not disjoint from -1 AE 0
|
||||
// 0 LT 1 is not disjoint from 0 BE 1
|
||||
// -1 LT 0 is not disjoint from -1 AT 0
|
||||
// 0 LT 1 is not disjoint from 0 BT 1
|
||||
return in(other, EQ, GT, GE);
|
||||
}
|
||||
case LE: {
|
||||
// 0 LE 0 is not disjoint from 0 EQ 0
|
||||
// 0 LE 1 is not disjoint from 0 NE 1
|
||||
// 0 LE 1 is not disjoint from 0 LT 1
|
||||
// 0 LE 0 is not disjoint from 0 GE 0
|
||||
// 0 LE 0 is not disjoint from 0 AE 0
|
||||
// 0 LE 0 is not disjoint from 0 BE 0
|
||||
// -1 LE 0 is not disjoint from -1 AT 0
|
||||
// 0 LE 1 is not disjoint from 0 BT 1
|
||||
return other == GT;
|
||||
}
|
||||
case GT: {
|
||||
// 0 GT -1 is not disjoint from 0 NE -1
|
||||
// 0 GT -1 is not disjoint from 0 GE -1
|
||||
// 1 GT 0 is not disjoint from 1 AE 0
|
||||
// 0 GT -1 is not disjoint from 0 BE -1
|
||||
// 1 GT 0 is not disjoint from 1 AT 0
|
||||
// 0 GT -1 is not disjoint from 0 BT -1
|
||||
return in(other, EQ, LT, LE);
|
||||
}
|
||||
case GE: {
|
||||
// 0 GE 0 is not disjoint from 0 EQ 0
|
||||
// 0 GE -1 is not disjoint from 0 NE -1
|
||||
// 0 GE 0 is not disjoint from 0 LE 0
|
||||
// 0 GE -1 is not disjoint from 0 GT -1
|
||||
// 0 GE 0 is not disjoint from 0 AE 0
|
||||
// 0 GE 0 is not disjoint from 0 BE 0
|
||||
// 1 GE 0 is not disjoint from 1 AT 0
|
||||
// 0 GE -1 is not disjoint from 0 BT -1
|
||||
return other == LT;
|
||||
}
|
||||
case AE: {
|
||||
// 0 AE 0 is not disjoint from 0 EQ 0
|
||||
// 1 AE 0 is not disjoint from 1 NE 0
|
||||
// -1 AE 0 is not disjoint from -1 LT 0
|
||||
// 0 AE 0 is not disjoint from 0 LE 0
|
||||
// 1 AE 0 is not disjoint from 1 GT 0
|
||||
// 0 AE 0 is not disjoint from 0 GE 0
|
||||
// 0 AE 0 is not disjoint from 0 BE 0
|
||||
// 1 AE 0 is not disjoint from 1 AT 0
|
||||
return other == BT;
|
||||
}
|
||||
case BE: {
|
||||
// 0 BE 0 is not disjoint from 0 EQ 0
|
||||
// 0 BE 1 is not disjoint from 0 NE 1
|
||||
// 0 BE 1 is not disjoint from 0 LT 1
|
||||
// 0 BE 0 is not disjoint from 0 LE 0
|
||||
// 0 BE -1 is not disjoint from 0 GT -1
|
||||
// 0 BE 0 is not disjoint from 0 GE 0
|
||||
// 0 BE 0 is not disjoint from 0 AE 0
|
||||
// 0 BE 1 is not disjoint from 0 BT 1
|
||||
return other == AT;
|
||||
}
|
||||
case AT: {
|
||||
// 1 AT 0 is not disjoint from 1 NE 0
|
||||
// -1 AT 0 is not disjoint from -1 LT 0
|
||||
// -1 AT 0 is not disjoint from -1 LE 0
|
||||
// 1 AT 0 is not disjoint from 1 GT 0
|
||||
// 1 AT 0 is not disjoint from 1 GE 0
|
||||
// 1 AT 0 is not disjoint from 1 AE 0
|
||||
return in(other, EQ, BE, BT);
|
||||
}
|
||||
case BT: {
|
||||
// 0 BT 1 is not disjoint from 0 NE 1
|
||||
// 0 BT 1 is not disjoint from 0 LT 1
|
||||
// 0 BT 1 is not disjoint from 0 LE 1
|
||||
// 0 BT -1 is not disjoint from 0 GT -1
|
||||
// 0 BT -1 is not disjoint from 0 GE -1
|
||||
// 0 BT 1 is not disjoint from 0 BE 1
|
||||
return in(other, EQ, AE, AT);
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException(this.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the join of this condition and {@code other}. Only non-null return values are
|
||||
* meaningful.
|
||||
*/
|
||||
public Condition join(Condition other) {
|
||||
if (other == this) {
|
||||
return this;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2020, 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
|
||||
@ -41,4 +41,6 @@ public interface CodeGenProviders {
|
||||
ForeignCallsProvider getForeignCalls();
|
||||
|
||||
ConstantReflectionProvider getConstantReflection();
|
||||
|
||||
MetaAccessExtensionProvider getMetaAccessExtensionProvider();
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2009, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -26,9 +26,11 @@ package org.graalvm.compiler.core.common.spi;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import jdk.internal.vm.compiler.word.LocationIdentity;
|
||||
|
||||
/**
|
||||
* The name and signature of a foreign call. A foreign call differs from a normal compiled Java call
|
||||
* in at least one of these aspects:
|
||||
* The information required for high level code generation of a foreign call. A foreign call differs
|
||||
* from a normal compiled Java call in at least one of these aspects:
|
||||
* <ul>
|
||||
* <li>The call is to C/C++/assembler code.</li>
|
||||
* <li>The call uses different conventions for passing parameters or returning values.</li>
|
||||
@ -42,59 +44,86 @@ import java.util.Arrays;
|
||||
*/
|
||||
public class ForeignCallDescriptor {
|
||||
|
||||
private final String name;
|
||||
private final Class<?> resultType;
|
||||
private final Class<?>[] argumentTypes;
|
||||
protected final ForeignCallSignature signature;
|
||||
protected final boolean isReexecutable;
|
||||
protected final boolean canDeoptimize;
|
||||
protected final boolean isGuaranteedSafepoint;
|
||||
protected final LocationIdentity[] killedLocations;
|
||||
|
||||
public ForeignCallDescriptor(String name, Class<?> resultType, Class<?>[] argumentTypes, boolean isReexecutable, LocationIdentity[] killedLocations, boolean canDeoptimize,
|
||||
boolean isGuaranteedSafepoint) {
|
||||
this.isReexecutable = isReexecutable;
|
||||
this.killedLocations = killedLocations;
|
||||
this.canDeoptimize = canDeoptimize;
|
||||
this.isGuaranteedSafepoint = isGuaranteedSafepoint;
|
||||
this.signature = new ForeignCallSignature(name, resultType, argumentTypes);
|
||||
|
||||
public ForeignCallDescriptor(String name, Class<?> resultType, Class<?>... argumentTypes) {
|
||||
this.name = name;
|
||||
this.resultType = resultType;
|
||||
this.argumentTypes = argumentTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of this foreign call.
|
||||
*/
|
||||
public ForeignCallSignature getSignature() {
|
||||
return signature;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
return signature.getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the return type of this foreign call.
|
||||
*/
|
||||
public Class<?> getResultType() {
|
||||
return resultType;
|
||||
return signature.getResultType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the argument types of this foreign call.
|
||||
*/
|
||||
public Class<?>[] getArgumentTypes() {
|
||||
return argumentTypes.clone();
|
||||
return signature.getArgumentTypes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return this == o;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return name.hashCode();
|
||||
return signature.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof ForeignCallDescriptor) {
|
||||
ForeignCallDescriptor other = (ForeignCallDescriptor) obj;
|
||||
return other.name.equals(name) && other.resultType.equals(resultType) && Arrays.equals(other.argumentTypes, argumentTypes);
|
||||
}
|
||||
return false;
|
||||
/**
|
||||
* Determines if a given foreign call is side-effect free. Deoptimization cannot return
|
||||
* execution to a point before a foreign call that has a side effect.
|
||||
*/
|
||||
public boolean isReexecutable() {
|
||||
return isReexecutable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the set of memory locations killed by a given foreign call. Returning the special value
|
||||
* {@link LocationIdentity#any()} denotes that the call kills all memory locations. Returning
|
||||
* any empty array denotes that the call does not kill any memory locations.
|
||||
*/
|
||||
public LocationIdentity[] getKilledLocations() {
|
||||
return killedLocations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if deoptimization can occur during a given foreign call.
|
||||
*/
|
||||
public boolean canDeoptimize() {
|
||||
return canDeoptimize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Identifies foreign calls which are guaranteed to include a safepoint check.
|
||||
*/
|
||||
public boolean isGuaranteedSafepoint() {
|
||||
return isGuaranteedSafepoint;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder(name).append('(');
|
||||
String sep = "";
|
||||
for (Class<?> arg : argumentTypes) {
|
||||
sb.append(sep).append(arg.getSimpleName());
|
||||
sep = ",";
|
||||
}
|
||||
return sb.append(')').append(resultType.getSimpleName()).toString();
|
||||
return getClass().getSimpleName() + "{" + signature +
|
||||
", isReexecutable=" + isReexecutable +
|
||||
", canDeoptimize=" + canDeoptimize +
|
||||
", isGuaranteedSafepoint=" + isGuaranteedSafepoint +
|
||||
", killedLocations=" + Arrays.toString(killedLocations) +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 2020, 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.spi;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* The name and signature of a {@link ForeignCallDescriptor foreign call}.
|
||||
*/
|
||||
public final class ForeignCallSignature {
|
||||
|
||||
private final String name;
|
||||
private final Class<?> resultType;
|
||||
private final Class<?>[] argumentTypes;
|
||||
|
||||
public ForeignCallSignature(String name, Class<?> resultType, Class<?>... argumentTypes) {
|
||||
this.name = name;
|
||||
this.resultType = resultType;
|
||||
this.argumentTypes = argumentTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of this foreign call.
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the return type of this foreign call.
|
||||
*/
|
||||
public Class<?> getResultType() {
|
||||
return resultType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the argument types of this foreign call.
|
||||
*/
|
||||
public Class<?>[] getArgumentTypes() {
|
||||
return argumentTypes.clone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return name.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof ForeignCallSignature) {
|
||||
ForeignCallSignature other = (ForeignCallSignature) obj;
|
||||
return other.name.equals(name) && other.resultType.equals(resultType) && Arrays.equals(other.argumentTypes, argumentTypes);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder(name).append('(');
|
||||
String sep = "";
|
||||
for (Class<?> arg : argumentTypes) {
|
||||
sb.append(sep).append(arg.getSimpleName());
|
||||
sep = ",";
|
||||
}
|
||||
return sb.append(')').append(resultType.getSimpleName()).toString();
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2020, 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
|
||||
@ -25,7 +25,6 @@
|
||||
package org.graalvm.compiler.core.common.spi;
|
||||
|
||||
import org.graalvm.compiler.core.common.LIRKind;
|
||||
import jdk.internal.vm.compiler.word.LocationIdentity;
|
||||
|
||||
import jdk.vm.ci.code.ValueKindFactory;
|
||||
|
||||
@ -34,36 +33,20 @@ import jdk.vm.ci.code.ValueKindFactory;
|
||||
*/
|
||||
public interface ForeignCallsProvider extends ValueKindFactory<LIRKind> {
|
||||
|
||||
/**
|
||||
* Determines if a given foreign call is side-effect free. Deoptimization cannot return
|
||||
* execution to a point before a foreign call that has a side effect.
|
||||
*/
|
||||
boolean isReexecutable(ForeignCallDescriptor descriptor);
|
||||
|
||||
/**
|
||||
* Gets the set of memory locations killed by a given foreign call. Returning the special value
|
||||
* {@link LocationIdentity#any()} denotes that the call kills all memory locations. Returning
|
||||
* any empty array denotes that the call does not kill any memory locations.
|
||||
*/
|
||||
LocationIdentity[] getKilledLocations(ForeignCallDescriptor descriptor);
|
||||
|
||||
/**
|
||||
* Determines if deoptimization can occur during a given foreign call.
|
||||
*/
|
||||
boolean canDeoptimize(ForeignCallDescriptor descriptor);
|
||||
|
||||
/**
|
||||
* Identifies foreign calls which are guaranteed to include a safepoint check.
|
||||
*/
|
||||
boolean isGuaranteedSafepoint(ForeignCallDescriptor descriptor);
|
||||
|
||||
/**
|
||||
* Gets the linkage for a foreign call.
|
||||
*/
|
||||
ForeignCallLinkage lookupForeignCall(ForeignCallDescriptor descriptor);
|
||||
|
||||
/**
|
||||
* Return true if the foreign call has a binding.
|
||||
* Gets the linkage for a foreign call.
|
||||
*/
|
||||
boolean isAvailable(ForeignCallDescriptor descriptor);
|
||||
default ForeignCallLinkage lookupForeignCall(ForeignCallSignature signature) {
|
||||
return lookupForeignCall(getDescriptor(signature));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the descriptor for a foreign call.
|
||||
*/
|
||||
ForeignCallDescriptor getDescriptor(ForeignCallSignature signature);
|
||||
}
|
||||
|
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2020, 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.spi;
|
||||
|
||||
import jdk.vm.ci.meta.JavaKind;
|
||||
import jdk.vm.ci.meta.JavaType;
|
||||
import jdk.vm.ci.meta.ResolvedJavaType;
|
||||
|
||||
/**
|
||||
* Provides additional meta data about JVMCI objects that is not provided by the VM itself, and
|
||||
* therefore does not need to be in JVMCI itself.
|
||||
*/
|
||||
public interface MetaAccessExtensionProvider {
|
||||
|
||||
/**
|
||||
* The {@link JavaKind} used to store the provided type in a field or array element. This can be
|
||||
* different than the {@link JavaType#getJavaKind} for types that are intercepted and
|
||||
* transformed by the compiler.
|
||||
*/
|
||||
JavaKind getStorageKind(JavaType type);
|
||||
|
||||
/**
|
||||
* Checks if a dynamic allocation of the provided type can be canonicalized to a regular
|
||||
* allocation node. If the method returns false, then the dynamic allocation would throw an
|
||||
* exception at run time and therefore canonicalization would miss that exception.
|
||||
*/
|
||||
boolean canConstantFoldDynamicAllocation(ResolvedJavaType type);
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2020, 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
|
||||
@ -339,14 +339,14 @@ public class FloatStamp extends PrimitiveStamp {
|
||||
if (Float.isNaN(value.asFloat())) {
|
||||
result = new FloatStamp(32, Double.NaN, Double.NaN, false);
|
||||
} else {
|
||||
result = new FloatStamp(32, value.asFloat(), value.asFloat(), !Float.isNaN(value.asFloat()));
|
||||
result = new FloatStamp(32, value.asFloat(), value.asFloat(), true);
|
||||
}
|
||||
break;
|
||||
case Double:
|
||||
if (Double.isNaN(value.asDouble())) {
|
||||
result = new FloatStamp(64, Double.NaN, Double.NaN, false);
|
||||
} else {
|
||||
result = new FloatStamp(64, value.asDouble(), value.asDouble(), !Double.isNaN(value.asDouble()));
|
||||
result = new FloatStamp(64, value.asDouble(), value.asDouble(), true);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2009, 2020, 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
|
||||
@ -44,6 +44,11 @@ public final class BitMap2D {
|
||||
}
|
||||
|
||||
public BitMap2D(int sizeInSlots, int bitsPerSlot) {
|
||||
long nBits = (long) sizeInSlots * bitsPerSlot;
|
||||
if (nBits > Integer.MAX_VALUE) {
|
||||
// Avoids issues where (sizeInSlots * bitsPerSlot) wraps around to a positive integer
|
||||
throw new OutOfMemoryError("Cannot allocate a BitSet for " + nBits + " bits");
|
||||
}
|
||||
map = new BitSet(sizeInSlots * bitsPerSlot);
|
||||
this.bitsPerSlot = bitsPerSlot;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2020, 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
|
||||
@ -548,7 +548,7 @@ public class MatchProcessor extends AbstractProcessor {
|
||||
}
|
||||
out.printf(" private static final String[] %s = new String[] {%s};\n", invoker.argumentsListName(), args);
|
||||
out.printf(" private static final class %s implements MatchGenerator {\n", invoker.wrapperClass());
|
||||
out.printf(" static MatchGenerator instance = new %s();\n", invoker.wrapperClass());
|
||||
out.printf(" static final MatchGenerator instance = new %s();\n", invoker.wrapperClass());
|
||||
out.printf(" @Override\n");
|
||||
out.printf(" public ComplexMatchResult match(NodeMatchRules nodeMatchRules, Object...args) {\n");
|
||||
out.printf(" return ((%s) nodeMatchRules).%s(%s);\n", invoker.nodeLIRBuilderClass, invoker.methodName, types);
|
||||
|
160
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ArrayCopyVirtualizationTest.java
Normal file
160
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ArrayCopyVirtualizationTest.java
Normal file
@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
package org.graalvm.compiler.core.test;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.graalvm.compiler.nodes.StructuredGraph;
|
||||
import org.graalvm.compiler.nodes.java.NewArrayNode;
|
||||
|
||||
public class ArrayCopyVirtualizationTest extends GraalCompilerTest {
|
||||
|
||||
@Override
|
||||
protected void checkMidTierGraph(StructuredGraph graph) {
|
||||
assertTrue(graph.getNodes().filter(node -> node instanceof NewArrayNode).count() == 0, "shouldn't require allocation in %s", graph);
|
||||
super.checkMidTierGraph(graph);
|
||||
}
|
||||
|
||||
public byte byteCopyVirtualization() {
|
||||
byte[] array = new byte[]{1, 2, 3, 4};
|
||||
System.arraycopy(array, 1, array, 0, 3);
|
||||
return array[0];
|
||||
}
|
||||
|
||||
public short shortCopyVirtualization() {
|
||||
short[] array = new short[]{1, 2, 3, 4};
|
||||
System.arraycopy(array, 1, array, 0, 2);
|
||||
return array[0];
|
||||
}
|
||||
|
||||
public char charCopyVirtualization() {
|
||||
char[] array = new char[]{1, 2, 3, 4};
|
||||
System.arraycopy(array, 1, array, 0, 3);
|
||||
return array[0];
|
||||
}
|
||||
|
||||
public int intCopyVirtualization() {
|
||||
int[] array = new int[]{1, 2, 3, 4};
|
||||
System.arraycopy(array, 1, array, 0, 3);
|
||||
return array[0];
|
||||
}
|
||||
|
||||
public long longCopyVirtualization() {
|
||||
long[] array = new long[]{1, 2, 3, 4};
|
||||
System.arraycopy(array, 1, array, 0, 3);
|
||||
return array[0];
|
||||
}
|
||||
|
||||
public float floatCopyVirtualization() {
|
||||
float[] array = new float[]{1, 2, 3, 4};
|
||||
System.arraycopy(array, 1, array, 0, 3);
|
||||
return array[0];
|
||||
}
|
||||
|
||||
public double doubleCopyVirtualization() {
|
||||
double[] array = new double[]{1, 2, 3, 4};
|
||||
System.arraycopy(array, 1, array, 0, 3);
|
||||
return array[0];
|
||||
}
|
||||
|
||||
public Object objectCopyVirtualization() {
|
||||
Object[] array = new Object[]{1, 2, 3, 4};
|
||||
System.arraycopy(array, 1, array, 0, 3);
|
||||
return array[0];
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCopyVirtualization() {
|
||||
test("byteCopyVirtualization");
|
||||
test("shortCopyVirtualization");
|
||||
test("charCopyVirtualization");
|
||||
test("intCopyVirtualization");
|
||||
test("longCopyVirtualization");
|
||||
test("floatCopyVirtualization");
|
||||
test("doubleCopyVirtualization");
|
||||
test("objectCopyVirtualization");
|
||||
}
|
||||
|
||||
public byte byteCopyBackwardsVirtualization() {
|
||||
byte[] array = new byte[]{1, 2, 3, 4};
|
||||
System.arraycopy(array, 0, array, 1, 3);
|
||||
return array[3];
|
||||
}
|
||||
|
||||
public short shortCopyBackwardsVirtualization() {
|
||||
short[] array = new short[]{1, 2, 3, 4};
|
||||
System.arraycopy(array, 0, array, 1, 3);
|
||||
return array[3];
|
||||
}
|
||||
|
||||
public char charCopyBackwardsVirtualization() {
|
||||
char[] array = new char[]{1, 2, 3, 4};
|
||||
System.arraycopy(array, 0, array, 1, 3);
|
||||
return array[3];
|
||||
}
|
||||
|
||||
public int intCopyBackwardsVirtualization() {
|
||||
int[] array = new int[]{1, 2, 3, 4};
|
||||
System.arraycopy(array, 0, array, 1, 3);
|
||||
return array[3];
|
||||
}
|
||||
|
||||
public long longCopyBackwardsVirtualization() {
|
||||
long[] array = new long[]{1, 2, 3, 4};
|
||||
System.arraycopy(array, 0, array, 1, 3);
|
||||
return array[3];
|
||||
}
|
||||
|
||||
public float floatCopyBackwardsVirtualization() {
|
||||
float[] array = new float[]{1, 2, 3, 4};
|
||||
System.arraycopy(array, 0, array, 1, 3);
|
||||
return array[3];
|
||||
}
|
||||
|
||||
public double doubleCopyBackwardsVirtualization() {
|
||||
double[] array = new double[]{1, 2, 3, 4};
|
||||
System.arraycopy(array, 0, array, 1, 3);
|
||||
return array[3];
|
||||
}
|
||||
|
||||
public Object objectCopyBackwardsVirtualization() {
|
||||
Object[] array = new Object[]{1, 2, 3, 4};
|
||||
System.arraycopy(array, 0, array, 1, 3);
|
||||
return array[3];
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCopyBackwardsVirtualization() {
|
||||
test("byteCopyBackwardsVirtualization");
|
||||
test("shortCopyBackwardsVirtualization");
|
||||
test("charCopyBackwardsVirtualization");
|
||||
test("intCopyBackwardsVirtualization");
|
||||
test("longCopyBackwardsVirtualization");
|
||||
test("floatCopyBackwardsVirtualization");
|
||||
test("doubleCopyBackwardsVirtualization");
|
||||
test("objectCopyBackwardsVirtualization");
|
||||
}
|
||||
}
|
@ -252,6 +252,21 @@ public class BoxingEliminationTest extends GraalCompilerTest {
|
||||
test("materializeTest1Snippet", 1);
|
||||
}
|
||||
|
||||
public static Float materializeTest2Snippet(float a) {
|
||||
Float v = a;
|
||||
|
||||
if (v == a) {
|
||||
return v;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void materializeTest2() {
|
||||
test("materializeTest2Snippet", 1f);
|
||||
}
|
||||
|
||||
public static int intTest1Snippet() {
|
||||
return Integer.valueOf(1);
|
||||
}
|
||||
|
@ -40,6 +40,7 @@ import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
@ -60,7 +61,7 @@ import org.graalvm.compiler.core.common.LIRKind;
|
||||
import org.graalvm.compiler.core.common.type.ArithmeticOpTable;
|
||||
import org.graalvm.compiler.debug.DebugCloseable;
|
||||
import org.graalvm.compiler.debug.DebugContext;
|
||||
import org.graalvm.compiler.debug.DebugHandlersFactory;
|
||||
import org.graalvm.compiler.debug.DebugContext.Builder;
|
||||
import org.graalvm.compiler.debug.GraalError;
|
||||
import org.graalvm.compiler.graph.Node;
|
||||
import org.graalvm.compiler.graph.NodeClass;
|
||||
@ -150,13 +151,23 @@ public class CheckGraalInvariants extends GraalCompilerTest {
|
||||
}
|
||||
|
||||
protected String getClassPath() {
|
||||
String bootclasspath;
|
||||
String classpath;
|
||||
if (JavaVersionUtil.JAVA_SPEC <= 8) {
|
||||
bootclasspath = System.getProperty("sun.boot.class.path");
|
||||
classpath = System.getProperty("sun.boot.class.path");
|
||||
} else {
|
||||
bootclasspath = JRT_CLASS_PATH_ENTRY;
|
||||
classpath = JRT_CLASS_PATH_ENTRY;
|
||||
}
|
||||
return bootclasspath;
|
||||
|
||||
// Also process classes that go into the libgraal native image.
|
||||
String javaClassPath = System.getProperty("java.class.path");
|
||||
if (javaClassPath != null) {
|
||||
for (String path : javaClassPath.split(File.pathSeparator)) {
|
||||
if (path.contains("libgraal") && !path.contains("processor")) {
|
||||
classpath += File.pathSeparator + path;
|
||||
}
|
||||
}
|
||||
}
|
||||
return classpath;
|
||||
}
|
||||
|
||||
protected boolean shouldLoadClass(String className) {
|
||||
@ -345,6 +356,8 @@ public class CheckGraalInvariants extends GraalCompilerTest {
|
||||
verifiers.add(new VerifyGetOptionsUsage());
|
||||
verifiers.add(new VerifyUnsafeAccess());
|
||||
|
||||
loadVerifiers(verifiers);
|
||||
|
||||
VerifyFoldableMethods foldableMethodsVerifier = new VerifyFoldableMethods();
|
||||
if (tool.shouldVerifyFoldableMethods()) {
|
||||
verifiers.add(foldableMethodsVerifier);
|
||||
@ -354,7 +367,7 @@ public class CheckGraalInvariants extends GraalCompilerTest {
|
||||
|
||||
for (Method m : BadUsageWithEquals.class.getDeclaredMethods()) {
|
||||
ResolvedJavaMethod method = metaAccess.lookupJavaMethod(m);
|
||||
try (DebugContext debug = DebugContext.create(options, DebugHandlersFactory.LOADER)) {
|
||||
try (DebugContext debug = new Builder(options).build()) {
|
||||
StructuredGraph graph = new StructuredGraph.Builder(options, debug, AllowAssumptions.YES).method(method).build();
|
||||
try (DebugCloseable s = debug.disableIntercept(); DebugContext.Scope ds = debug.scope("CheckingGraph", graph, method)) {
|
||||
graphBuilderSuite.apply(graph, context);
|
||||
@ -408,7 +421,7 @@ public class CheckGraalInvariants extends GraalCompilerTest {
|
||||
String methodName = className + "." + method.getName();
|
||||
if (matches(filters, methodName)) {
|
||||
executor.execute(() -> {
|
||||
try (DebugContext debug = DebugContext.create(options, DebugHandlersFactory.LOADER)) {
|
||||
try (DebugContext debug = new Builder(options).build()) {
|
||||
boolean isSubstitution = method.getAnnotation(Snippet.class) != null || method.getAnnotation(MethodSubstitution.class) != null;
|
||||
StructuredGraph graph = new StructuredGraph.Builder(options, debug).method(method).setIsSubstitution(isSubstitution).build();
|
||||
try (DebugCloseable s = debug.disableIntercept(); DebugContext.Scope ds = debug.scope("CheckingGraph", graph, method)) {
|
||||
@ -471,6 +484,13 @@ public class CheckGraalInvariants extends GraalCompilerTest {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static void loadVerifiers(List<VerifyPhase<CoreProviders>> verifiers) {
|
||||
for (VerifyPhase<CoreProviders> verifier : ServiceLoader.load(VerifyPhase.class)) {
|
||||
verifiers.add(verifier);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes a map from a field annotated by {@link Option} to a set that will be used to
|
||||
* collect methods that accesses the option field.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2020, 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
|
||||
@ -108,4 +108,27 @@ public class ConditionTest {
|
||||
}
|
||||
}
|
||||
|
||||
static int[] intBoundaryValues = new int[]{-1, 0, 1, Integer.MIN_VALUE, Integer.MIN_VALUE + 1, Integer.MAX_VALUE - 1, Integer.MAX_VALUE};
|
||||
|
||||
@Test
|
||||
public void testTrueIsDisjoint() {
|
||||
for (Condition c1 : Condition.values()) {
|
||||
for (Condition c2 : Condition.values()) {
|
||||
if (c1.trueIsDisjoint(c2)) {
|
||||
for (int v1 : intBoundaryValues) {
|
||||
for (int v2 : intBoundaryValues) {
|
||||
JavaConstant a = JavaConstant.forInt(v1);
|
||||
JavaConstant b = JavaConstant.forInt(v2);
|
||||
boolean result1 = c1.foldCondition(a, b, null, false);
|
||||
boolean result2 = c2.foldCondition(a, b, null, false);
|
||||
// If these conditions are disjoint then both conditions can't evaluate
|
||||
// to true for the same inputs.
|
||||
assertFalse(String.format("%s %s %s (%s) is not disjoint from %s %s %s (%s)", a, c1, b, result1, a, c2, b, result2), result1 && result2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2020, 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
|
||||
@ -93,7 +93,7 @@ public class GuardPrioritiesTest extends GraphScheduleTest {
|
||||
return graph;
|
||||
}
|
||||
|
||||
public int unknownCondition(Integer c, Object o, int[] a, Integer i) {
|
||||
public int unknownCondition(int c, Object o, int[] a, int i) {
|
||||
if (o != null) {
|
||||
GraalDirectives.deoptimizeAndInvalidate();
|
||||
}
|
||||
|
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
|
||||
package org.graalvm.compiler.core.test;
|
||||
|
||||
import static org.graalvm.compiler.api.directives.GraalDirectives.injectBranchProbability;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Test extracted from reproducer in https://github.com/oracle/graal/issues/2493.
|
||||
*/
|
||||
public class IfCanonicalizerSwapTest extends GraalCompilerTest {
|
||||
public static String testSnippet1(long value) {
|
||||
if (injectBranchProbability(0.50, value >= 0L) && injectBranchProbability(0.00, value <= 35L)) {
|
||||
return "JustRight";
|
||||
} else {
|
||||
if (injectBranchProbability(0.50, value > 35L)) {
|
||||
return "TooHot";
|
||||
} else {
|
||||
return "TooCold";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test1() {
|
||||
test("testSnippet1", -1L);
|
||||
test("testSnippet1", 100L);
|
||||
test("testSnippet1", 10L);
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, Red Hat Inc. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -26,17 +26,20 @@
|
||||
|
||||
package org.graalvm.compiler.core.test;
|
||||
|
||||
import jdk.vm.ci.aarch64.AArch64;
|
||||
import jdk.vm.ci.meta.ConstantReflectionProvider;
|
||||
import jdk.vm.ci.meta.MetaAccessProvider;
|
||||
import jdk.vm.ci.meta.ResolvedJavaType;
|
||||
import jdk.internal.vm.compiler.collections.EconomicMap;
|
||||
import org.graalvm.compiler.core.common.type.Stamp;
|
||||
import org.graalvm.compiler.graph.Node;
|
||||
import org.graalvm.compiler.nodes.ConstantNode;
|
||||
import org.graalvm.compiler.nodes.NodeView;
|
||||
import org.graalvm.compiler.nodes.StructuredGraph;
|
||||
import org.graalvm.compiler.nodes.ValueNode;
|
||||
import org.graalvm.compiler.nodes.cfg.Block;
|
||||
import org.graalvm.compiler.nodes.cfg.ControlFlowGraph;
|
||||
import org.graalvm.compiler.nodes.extended.MembarNode;
|
||||
import org.graalvm.compiler.nodes.memory.FixedAccessNode;
|
||||
import org.graalvm.compiler.nodes.memory.MemoryAccess;
|
||||
import org.graalvm.compiler.nodes.memory.ReadNode;
|
||||
@ -78,7 +81,7 @@ public class LateMembarInsertionTest extends GraalCompilerTest {
|
||||
|
||||
@Test
|
||||
public void test01() {
|
||||
List<TypePair> accesses = compile("volatileFieldLoadFieldLoad", stressTestEarlyReads());
|
||||
List<TypePair> accesses = getAccesses("volatileFieldLoadFieldLoad", stressTestEarlyReads());
|
||||
|
||||
Assert.assertEquals(accesses.size(), 2);
|
||||
Assert.assertEquals(accesses.get(0).getType(), volatileAccessType);
|
||||
@ -95,7 +98,7 @@ public class LateMembarInsertionTest extends GraalCompilerTest {
|
||||
|
||||
@Test
|
||||
public void test02() {
|
||||
List<TypePair> accesses = compile("volatileFieldLoadVolatileFieldLoad", stressTestEarlyReads());
|
||||
List<TypePair> accesses = getAccesses("volatileFieldLoadVolatileFieldLoad", stressTestEarlyReads());
|
||||
|
||||
Assert.assertEquals(accesses.size(), 2);
|
||||
Assert.assertEquals(accesses.get(0).getType(), volatileAccessType);
|
||||
@ -112,7 +115,7 @@ public class LateMembarInsertionTest extends GraalCompilerTest {
|
||||
|
||||
@Test
|
||||
public void test03() {
|
||||
List<TypePair> accesses = compile("volatileFieldLoadVolatileFieldStore");
|
||||
List<TypePair> accesses = getAccesses("volatileFieldLoadVolatileFieldStore");
|
||||
|
||||
Assert.assertEquals(accesses.size(), 2);
|
||||
Assert.assertEquals(accesses.get(0).getType(), volatileAccessType);
|
||||
@ -128,7 +131,7 @@ public class LateMembarInsertionTest extends GraalCompilerTest {
|
||||
|
||||
@Test
|
||||
public void test04() {
|
||||
List<TypePair> accesses = compile("volatileFieldStoreVolatileFieldLoad", stressTestEarlyReads());
|
||||
List<TypePair> accesses = getAccesses("volatileFieldStoreVolatileFieldLoad", stressTestEarlyReads());
|
||||
|
||||
Assert.assertEquals(accesses.size(), 2);
|
||||
Assert.assertEquals(accesses.get(0).getType(), volatileAccessType);
|
||||
@ -145,7 +148,7 @@ public class LateMembarInsertionTest extends GraalCompilerTest {
|
||||
|
||||
@Test
|
||||
public void test05() {
|
||||
List<TypePair> accesses = compile("fieldLoadVolatileFieldStore");
|
||||
List<TypePair> accesses = getAccesses("fieldLoadVolatileFieldStore");
|
||||
|
||||
Assert.assertEquals(accesses.size(), 2);
|
||||
Assert.assertEquals(accesses.get(0).getType(), regularAccessField);
|
||||
@ -161,7 +164,7 @@ public class LateMembarInsertionTest extends GraalCompilerTest {
|
||||
|
||||
@Test
|
||||
public void test06() {
|
||||
List<TypePair> accesses = compile("volatileFieldStoreVolatileFieldStore");
|
||||
List<TypePair> accesses = getAccesses("volatileFieldStoreVolatileFieldStore");
|
||||
|
||||
Assert.assertEquals(accesses.size(), 2);
|
||||
Assert.assertEquals(accesses.get(0).getType(), volatileAccessType);
|
||||
@ -170,6 +173,119 @@ public class LateMembarInsertionTest extends GraalCompilerTest {
|
||||
Assert.assertTrue(accesses.get(1).isWrite());
|
||||
}
|
||||
|
||||
public static int volatileFieldLoad() {
|
||||
return VolatileAccess.field;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test07() {
|
||||
verifyMembars("volatileFieldLoad", membarsExpected());
|
||||
}
|
||||
|
||||
private boolean membarsExpected() {
|
||||
return !(getTarget().arch instanceof AArch64);
|
||||
}
|
||||
|
||||
public static void volatileFieldStore(int v) {
|
||||
VolatileAccess.field = v;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test08() {
|
||||
verifyMembars("volatileFieldStore", membarsExpected());
|
||||
}
|
||||
|
||||
// Unused field load should be optimized out and leave no barrier behind
|
||||
@SuppressWarnings("unused")
|
||||
public static void volatileFieldStoreUnusedVolatileFieldLoadVolatileFieldStore(int v2) {
|
||||
VolatileAccess2.field = v2;
|
||||
int v1 = VolatileAccess.field;
|
||||
VolatileAccess2.field = v2;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test09() {
|
||||
StructuredGraph graph = getFinalGraph(getResolvedJavaMethod("volatileFieldStoreUnusedVolatileFieldLoadVolatileFieldStore"));
|
||||
List<TypePair> accesses = getAccesses(graph);
|
||||
|
||||
Assert.assertEquals(accesses.size(), 2);
|
||||
Assert.assertEquals(accesses.get(0).getType(), volatileAccess2Type);
|
||||
Assert.assertEquals(accesses.get(1).getType(), volatileAccess2Type);
|
||||
Assert.assertTrue(accesses.get(0).isWrite());
|
||||
Assert.assertTrue(accesses.get(1).isWrite());
|
||||
Assert.assertEquals(membarsExpected() ? 4 : 0, getMembars(graph).size());
|
||||
}
|
||||
|
||||
// Unused field load should be optimized out and leave no barrier behind
|
||||
@SuppressWarnings("unused")
|
||||
public static void unusedVolatileFieldLoadVolatileFieldStore(int v2) {
|
||||
int v1 = VolatileAccess.field;
|
||||
VolatileAccess2.field = v2;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test10() {
|
||||
StructuredGraph graph = getFinalGraph(getResolvedJavaMethod("unusedVolatileFieldLoadVolatileFieldStore"));
|
||||
List<TypePair> accesses = getAccesses(graph);
|
||||
|
||||
Assert.assertEquals(accesses.size(), 1);
|
||||
Assert.assertEquals(accesses.get(0).getType(), volatileAccess2Type);
|
||||
Assert.assertTrue(accesses.get(0).isWrite());
|
||||
Assert.assertEquals(membarsExpected() ? 2 : 0, getMembars(graph).size());
|
||||
}
|
||||
|
||||
public static int unsafeVolatileFieldLoad(Object o, long offset) {
|
||||
return UNSAFE.getIntVolatile(o, offset);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test11() {
|
||||
verifyMembars("unsafeVolatileFieldLoad", membarsExpected());
|
||||
}
|
||||
|
||||
public static void unsafeVolatileFieldStore(Object o, long offset, int v) {
|
||||
UNSAFE.putIntVolatile(o, offset, v);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test12() {
|
||||
verifyMembars("unsafeVolatileFieldStore", membarsExpected());
|
||||
}
|
||||
|
||||
private void verifyMembars(String method, boolean expectsMembar) {
|
||||
StructuredGraph graph = getFinalGraph(getResolvedJavaMethod(method));
|
||||
StructuredGraph.ScheduleResult schedule = graph.getLastSchedule();
|
||||
ControlFlowGraph cfg = schedule.getCFG();
|
||||
Block[] blocks = cfg.getBlocks();
|
||||
Assert.assertEquals(blocks.length, 1);
|
||||
Block block = blocks[0];
|
||||
List<Node> nodes = schedule.nodesFor(block);
|
||||
Node preBarrier = null;
|
||||
Node postBarrier = null;
|
||||
Node mem = null;
|
||||
for (int i = 0; i < nodes.size(); i++) {
|
||||
Node node = nodes.get(i);
|
||||
if (node instanceof MembarNode) {
|
||||
if (preBarrier == null) {
|
||||
Assert.assertNull(mem);
|
||||
preBarrier = node;
|
||||
} else {
|
||||
Assert.assertNull(postBarrier);
|
||||
Assert.assertNotNull(mem);
|
||||
postBarrier = node;
|
||||
}
|
||||
} else if (node instanceof MemoryAccess) {
|
||||
Assert.assertEquals(preBarrier != null, expectsMembar);
|
||||
Assert.assertNull(postBarrier);
|
||||
Assert.assertNull(mem);
|
||||
mem = node;
|
||||
}
|
||||
}
|
||||
Assert.assertEquals(preBarrier != null, expectsMembar);
|
||||
Assert.assertEquals(postBarrier != null, expectsMembar);
|
||||
Assert.assertNotNull(mem);
|
||||
}
|
||||
|
||||
private static OptionValues stressTestEarlyReads() {
|
||||
EconomicMap<OptionKey<?>, Object> overrides = OptionValues.newOptionMap();
|
||||
overrides.put(StressTestEarlyReads, true);
|
||||
@ -198,7 +314,7 @@ public class LateMembarInsertionTest extends GraalCompilerTest {
|
||||
}
|
||||
}
|
||||
|
||||
private List<TypePair> compile(String test, OptionValues options) {
|
||||
private List<TypePair> getAccesses(String test, OptionValues options) {
|
||||
StructuredGraph graph = getFinalGraph(getResolvedJavaMethod(test), options);
|
||||
return getAccesses(graph);
|
||||
}
|
||||
@ -212,7 +328,7 @@ public class LateMembarInsertionTest extends GraalCompilerTest {
|
||||
n -> new TypePair(n instanceof ReadNode, classForAccess((FixedAccessNode) n))).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private List<TypePair> compile(String test) {
|
||||
private List<TypePair> getAccesses(String test) {
|
||||
StructuredGraph graph = getFinalGraph(getResolvedJavaMethod(test));
|
||||
return getAccesses(graph);
|
||||
}
|
||||
@ -230,4 +346,11 @@ public class LateMembarInsertionTest extends GraalCompilerTest {
|
||||
return javaType;
|
||||
}
|
||||
|
||||
private static List<Node> getMembars(StructuredGraph graph) {
|
||||
StructuredGraph.ScheduleResult schedule = graph.getLastSchedule();
|
||||
ControlFlowGraph cfg = schedule.getCFG();
|
||||
Block[] blocks = cfg.getBlocks();
|
||||
|
||||
return Arrays.stream(blocks).flatMap(b -> schedule.nodesFor(b).stream()).filter(n -> n instanceof MembarNode).collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2020, 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
|
||||
@ -28,8 +28,8 @@ import org.graalvm.compiler.loop.DefaultLoopPolicies;
|
||||
import org.graalvm.compiler.loop.phases.LoopFullUnrollPhase;
|
||||
import org.graalvm.compiler.nodes.StructuredGraph;
|
||||
import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
|
||||
import org.graalvm.compiler.nodes.java.MonitorEnterNode;
|
||||
import org.graalvm.compiler.nodes.java.MonitorExitNode;
|
||||
import org.graalvm.compiler.nodes.java.RawMonitorEnterNode;
|
||||
import org.graalvm.compiler.nodes.spi.LoweringTool;
|
||||
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
|
||||
import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase;
|
||||
@ -71,7 +71,7 @@ public class LockEliminationTest extends GraalCompilerTest {
|
||||
StructuredGraph graph = getGraph("testSynchronizedSnippet", false);
|
||||
createCanonicalizerPhase().apply(graph, getProviders());
|
||||
new LockEliminationPhase().apply(graph);
|
||||
assertDeepEquals(1, graph.getNodes().filter(RawMonitorEnterNode.class).count());
|
||||
assertDeepEquals(1, graph.getNodes().filter(MonitorEnterNode.class).count());
|
||||
assertDeepEquals(1, graph.getNodes().filter(MonitorExitNode.class).count());
|
||||
}
|
||||
|
||||
@ -89,7 +89,7 @@ public class LockEliminationTest extends GraalCompilerTest {
|
||||
StructuredGraph graph = getGraph("testSynchronizedMethodSnippet", false);
|
||||
createCanonicalizerPhase().apply(graph, getProviders());
|
||||
new LockEliminationPhase().apply(graph);
|
||||
assertDeepEquals(1, graph.getNodes().filter(RawMonitorEnterNode.class).count());
|
||||
assertDeepEquals(1, graph.getNodes().filter(MonitorEnterNode.class).count());
|
||||
assertDeepEquals(1, graph.getNodes().filter(MonitorExitNode.class).count());
|
||||
}
|
||||
|
||||
@ -109,7 +109,7 @@ public class LockEliminationTest extends GraalCompilerTest {
|
||||
HighTierContext context = getDefaultHighTierContext();
|
||||
new LoopFullUnrollPhase(canonicalizer, new DefaultLoopPolicies()).apply(graph, context);
|
||||
new LockEliminationPhase().apply(graph);
|
||||
assertDeepEquals(1, graph.getNodes().filter(RawMonitorEnterNode.class).count());
|
||||
assertDeepEquals(1, graph.getNodes().filter(MonitorEnterNode.class).count());
|
||||
assertDeepEquals(1, graph.getNodes().filter(MonitorExitNode.class).count());
|
||||
}
|
||||
|
||||
@ -157,12 +157,12 @@ public class LockEliminationTest extends GraalCompilerTest {
|
||||
public void testEscapeAnalysis() {
|
||||
StructuredGraph graph = getGraph("testEscapeAnalysisSnippet", true);
|
||||
|
||||
assertDeepEquals(3, graph.getNodes().filter(RawMonitorEnterNode.class).count());
|
||||
assertDeepEquals(3, graph.getNodes().filter(MonitorEnterNode.class).count());
|
||||
assertDeepEquals(3, graph.getNodes().filter(MonitorExitNode.class).count());
|
||||
|
||||
new LockEliminationPhase().apply(graph);
|
||||
|
||||
assertDeepEquals(2, graph.getNodes().filter(RawMonitorEnterNode.class).count());
|
||||
assertDeepEquals(2, graph.getNodes().filter(MonitorEnterNode.class).count());
|
||||
assertDeepEquals(2, graph.getNodes().filter(MonitorExitNode.class).count());
|
||||
}
|
||||
}
|
||||
|
@ -24,12 +24,7 @@
|
||||
|
||||
package org.graalvm.compiler.core.test;
|
||||
|
||||
import jdk.vm.ci.meta.JavaConstant;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.graalvm.compiler.debug.DebugHandlersFactory;
|
||||
import org.graalvm.compiler.debug.DebugContext;
|
||||
import org.graalvm.compiler.debug.DebugContext.Builder;
|
||||
import org.graalvm.compiler.nodes.ConstantNode;
|
||||
import org.graalvm.compiler.nodes.ReturnNode;
|
||||
import org.graalvm.compiler.nodes.StructuredGraph;
|
||||
@ -40,6 +35,10 @@ import org.graalvm.compiler.options.OptionValues;
|
||||
import org.graalvm.compiler.phases.schedule.SchedulePhase;
|
||||
import org.graalvm.compiler.phases.schedule.SchedulePhase.SchedulingStrategy;
|
||||
import org.graalvm.compiler.phases.tiers.HighTierContext;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import jdk.vm.ci.meta.JavaConstant;
|
||||
|
||||
public class LongNodeChainTest extends GraalCompilerTest {
|
||||
|
||||
@ -56,7 +55,7 @@ public class LongNodeChainTest extends GraalCompilerTest {
|
||||
private void longAddChain(boolean reverse) {
|
||||
HighTierContext context = getDefaultHighTierContext();
|
||||
OptionValues options = getInitialOptions();
|
||||
StructuredGraph graph = new StructuredGraph.Builder(options, DebugContext.create(options, DebugHandlersFactory.LOADER)).build();
|
||||
StructuredGraph graph = new StructuredGraph.Builder(options, new Builder(options).build()).build();
|
||||
ValueNode constant = graph.unique(ConstantNode.forPrimitive(JavaConstant.INT_1));
|
||||
ValueNode value = null;
|
||||
if (reverse) {
|
||||
|
@ -25,13 +25,11 @@
|
||||
|
||||
package org.graalvm.compiler.core.test;
|
||||
|
||||
import org.graalvm.compiler.api.test.Graal;
|
||||
import org.graalvm.compiler.nodes.StructuredGraph;
|
||||
import org.graalvm.compiler.nodes.memory.WriteNode;
|
||||
import org.graalvm.compiler.nodes.spi.LoweringTool;
|
||||
import org.graalvm.compiler.phases.common.FloatingReadPhase;
|
||||
import org.graalvm.compiler.phases.common.IncrementalCanonicalizerPhase;
|
||||
import org.graalvm.compiler.phases.common.LoweringPhase;
|
||||
import org.graalvm.compiler.phases.tiers.HighTierContext;
|
||||
import org.graalvm.compiler.phases.tiers.Suites;
|
||||
import org.graalvm.compiler.runtime.RuntimeProvider;
|
||||
import org.junit.Test;
|
||||
|
||||
public class MemoryGraphCanonicalizeTest extends GraalCompilerTest {
|
||||
@ -69,15 +67,15 @@ public class MemoryGraphCanonicalizeTest extends GraalCompilerTest {
|
||||
|
||||
@Test
|
||||
public void testComplexElimination() {
|
||||
testGraph("complexElimination", 6);
|
||||
testGraph("complexElimination", 5);
|
||||
}
|
||||
|
||||
public void testGraph(String name, int expectedWrites) {
|
||||
StructuredGraph graph = parseEager(name, StructuredGraph.AllowAssumptions.YES);
|
||||
HighTierContext context = getDefaultHighTierContext();
|
||||
new LoweringPhase(createCanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
|
||||
new IncrementalCanonicalizerPhase<>(createCanonicalizerPhase(), new FloatingReadPhase()).apply(graph, context);
|
||||
createCanonicalizerPhase().apply(graph, context);
|
||||
Suites s = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getSuites().getDefaultSuites(getInitialOptions());
|
||||
s.getHighTier().apply(graph, getDefaultHighTierContext());
|
||||
s.getMidTier().apply(graph, getDefaultMidTierContext());
|
||||
|
||||
int writes = graph.getNodes().filter(WriteNode.class).count();
|
||||
assertTrue(writes == expectedWrites, "Expected %d writes, found %d", expectedWrites, writes);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2020, 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
|
||||
@ -40,6 +40,7 @@ import org.graalvm.compiler.graph.iterators.NodeIterable;
|
||||
import org.graalvm.compiler.nodes.ReturnNode;
|
||||
import org.graalvm.compiler.nodes.StructuredGraph;
|
||||
import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
|
||||
import org.graalvm.compiler.nodes.StructuredGraph.GuardsStage;
|
||||
import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult;
|
||||
import org.graalvm.compiler.nodes.cfg.Block;
|
||||
import org.graalvm.compiler.nodes.memory.FloatingReadNode;
|
||||
@ -699,16 +700,20 @@ public class MemoryScheduleTest extends GraphScheduleTest {
|
||||
createInliningPhase(canonicalizer).apply(graph, context);
|
||||
}
|
||||
new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
|
||||
if (mode == TestMode.WITHOUT_FRAMESTATES || mode == TestMode.INLINED_WITHOUT_FRAMESTATES) {
|
||||
graph.clearAllStateAfter();
|
||||
}
|
||||
debug.dump(DebugContext.BASIC_LEVEL, graph, "after removal of framestates");
|
||||
|
||||
new FloatingReadPhase().apply(graph);
|
||||
new RemoveValueProxyPhase().apply(graph);
|
||||
|
||||
MidTierContext midContext = new MidTierContext(getProviders(), getTargetProvider(), OptimisticOptimizations.ALL, graph.getProfilingInfo());
|
||||
new GuardLoweringPhase().apply(graph, midContext);
|
||||
|
||||
if (mode == TestMode.WITHOUT_FRAMESTATES || mode == TestMode.INLINED_WITHOUT_FRAMESTATES) {
|
||||
graph.clearAllStateAfter();
|
||||
// disable stat split verification
|
||||
graph.setGuardsStage(GuardsStage.AFTER_FSA);
|
||||
}
|
||||
debug.dump(DebugContext.BASIC_LEVEL, graph, "after removal of framestates");
|
||||
|
||||
new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.MID_TIER).apply(graph, midContext);
|
||||
new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.LOW_TIER).apply(graph, midContext);
|
||||
|
||||
|
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, 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.test;
|
||||
|
||||
import org.graalvm.compiler.nodes.StructuredGraph;
|
||||
import org.graalvm.compiler.nodes.calc.NegateNode;
|
||||
import org.graalvm.compiler.nodes.calc.RightShiftNode;
|
||||
import org.graalvm.compiler.nodes.calc.UnsignedRightShiftNode;
|
||||
import org.junit.Test;
|
||||
|
||||
public class NegateCanonicalizationTest extends GraalCompilerTest {
|
||||
|
||||
public static int negateInt(int x) {
|
||||
return -(x >> 31);
|
||||
}
|
||||
|
||||
public static long negateLong(long x) {
|
||||
return -(x >> 63);
|
||||
}
|
||||
|
||||
public static int signExtractInt(int x) {
|
||||
return (x >> 31) >>> 31;
|
||||
}
|
||||
|
||||
public static long signExtractLong(long x) {
|
||||
return (x >> 63) >>> 63;
|
||||
}
|
||||
|
||||
private void checkNodes(String methodName) {
|
||||
StructuredGraph graph = parseForCompile(getResolvedJavaMethod(methodName));
|
||||
createCanonicalizerPhase().apply(graph, getProviders());
|
||||
assertTrue(graph.getNodes().filter(NegateNode.class).count() == 0);
|
||||
assertTrue(graph.getNodes().filter(RightShiftNode.class).count() == 0);
|
||||
assertTrue(graph.getNodes().filter(UnsignedRightShiftNode.class).count() == 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNegate() {
|
||||
checkNodes("negateInt");
|
||||
checkNodes("negateLong");
|
||||
checkNodes("signExtractInt");
|
||||
checkNodes("signExtractLong");
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2020, 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
|
||||
@ -29,9 +29,8 @@ import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_IGNORED;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.graalvm.compiler.core.common.PermanentBailoutException;
|
||||
import org.graalvm.compiler.debug.DebugContext;
|
||||
import org.graalvm.compiler.graph.Node;
|
||||
import org.graalvm.compiler.graph.NodeClass;
|
||||
import org.graalvm.compiler.graph.NodeInputList;
|
||||
@ -39,10 +38,15 @@ import org.graalvm.compiler.graph.NodeSuccessorList;
|
||||
import org.graalvm.compiler.graph.Position;
|
||||
import org.graalvm.compiler.graph.iterators.NodeIterable;
|
||||
import org.graalvm.compiler.nodeinfo.NodeInfo;
|
||||
import org.graalvm.compiler.nodes.AbstractMergeNode;
|
||||
import org.graalvm.compiler.nodes.ConstantNode;
|
||||
import org.graalvm.compiler.nodes.EndNode;
|
||||
import org.graalvm.compiler.nodes.MergeNode;
|
||||
import org.graalvm.compiler.nodes.StructuredGraph;
|
||||
import org.graalvm.compiler.nodes.ValueNode;
|
||||
import org.graalvm.compiler.nodes.calc.FloatingNode;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class NodePosIteratorTest extends GraalCompilerTest {
|
||||
|
||||
@ -63,6 +67,27 @@ public class NodePosIteratorTest extends GraalCompilerTest {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNodeInputIteratorLimit() {
|
||||
DebugContext debug = getDebugContext();
|
||||
StructuredGraph graph = new StructuredGraph.Builder(debug.getOptions(), debug,
|
||||
StructuredGraph.AllowAssumptions.YES).build();
|
||||
|
||||
AbstractMergeNode merge = graph.add(new MergeNode());
|
||||
for (int i = 0; i < 65536; i++) {
|
||||
EndNode end = graph.add(new EndNode());
|
||||
merge.addForwardEnd(end);
|
||||
}
|
||||
merge.inputs().count();
|
||||
EndNode end = graph.add(new EndNode());
|
||||
try {
|
||||
merge.addForwardEnd(end);
|
||||
} catch (PermanentBailoutException e) {
|
||||
return;
|
||||
}
|
||||
Assert.fail("Expected a permanent bailout exception due to too high number of inputs");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInputs() {
|
||||
TestNode n = new TestNode();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2020, 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
|
||||
@ -62,6 +62,7 @@ public class SchedulingTest extends GraphScheduleTest {
|
||||
fs.replaceAtUsages(null);
|
||||
GraphUtil.killWithUnusedFloatingInputs(fs);
|
||||
}
|
||||
graph.clearAllStateAfter();
|
||||
SchedulePhase schedulePhase = new SchedulePhase(SchedulingStrategy.LATEST);
|
||||
schedulePhase.apply(graph);
|
||||
ScheduleResult schedule = graph.getLastSchedule();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2020, 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
|
||||
@ -25,6 +25,7 @@
|
||||
package org.graalvm.compiler.core.test;
|
||||
|
||||
import org.graalvm.compiler.debug.DebugContext;
|
||||
import org.graalvm.compiler.debug.DebugContext.Builder;
|
||||
import org.graalvm.compiler.nodes.AbstractBeginNode;
|
||||
import org.graalvm.compiler.nodes.AbstractMergeNode;
|
||||
import org.graalvm.compiler.nodes.BeginNode;
|
||||
@ -51,7 +52,7 @@ public class SimpleCFGTest extends GraalCompilerTest {
|
||||
@Test
|
||||
public void testImplies() {
|
||||
OptionValues options = getInitialOptions();
|
||||
DebugContext debug = DebugContext.create(options, new GraalDebugHandlersFactory(getSnippetReflection()));
|
||||
DebugContext debug = new Builder(options, new GraalDebugHandlersFactory(getSnippetReflection())).build();
|
||||
StructuredGraph graph = new StructuredGraph.Builder(options, debug, AllowAssumptions.YES).build();
|
||||
|
||||
EndNode trueEnd = graph.add(new EndNode());
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2020, 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
|
||||
@ -30,8 +30,8 @@ import java.lang.reflect.Method;
|
||||
|
||||
import org.graalvm.compiler.api.test.Graal;
|
||||
import org.graalvm.compiler.debug.DebugCloseable;
|
||||
import org.graalvm.compiler.debug.DebugHandlersFactory;
|
||||
import org.graalvm.compiler.debug.DebugContext;
|
||||
import org.graalvm.compiler.debug.DebugContext.Builder;
|
||||
import org.graalvm.compiler.java.GraphBuilderPhase;
|
||||
import org.graalvm.compiler.nodes.StructuredGraph;
|
||||
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
|
||||
@ -93,7 +93,7 @@ public class StaticInterfaceFieldTest extends GraalTest {
|
||||
final Method m = getMethod(clazz, methodName);
|
||||
ResolvedJavaMethod method = metaAccess.lookupJavaMethod(m);
|
||||
OptionValues options = getInitialOptions();
|
||||
DebugContext debug = DebugContext.create(options, DebugHandlersFactory.LOADER);
|
||||
DebugContext debug = new Builder(options).build();
|
||||
StructuredGraph graph = new StructuredGraph.Builder(options, debug).method(method).build();
|
||||
try (DebugCloseable s = debug.disableIntercept(); DebugContext.Scope ds = debug.scope("GraphBuilding", graph, method)) {
|
||||
graphBuilderSuite.apply(graph, context);
|
||||
|
@ -282,6 +282,7 @@ public class UnsafeVirtualizationTest extends GraalCompilerTest {
|
||||
} else {
|
||||
UNSAFE.putLong(t, getUnsafeByteArrayOffset(0), l2);
|
||||
}
|
||||
sideEffect();
|
||||
if (c) {
|
||||
GraalDirectives.deoptimize();
|
||||
}
|
||||
@ -495,7 +496,7 @@ public class UnsafeVirtualizationTest extends GraalCompilerTest {
|
||||
VirtualObjectNode virtual = graph.getNodes().filter(VirtualObjectNode.class).first();
|
||||
if (virtual instanceof VirtualArrayNode) {
|
||||
VirtualArrayNode array = (VirtualArrayNode) virtual;
|
||||
if (array.isVirtualByteArray()) {
|
||||
if (array.isVirtualByteArray(context.getMetaAccessExtensionProvider())) {
|
||||
canVirtualize = context.getPlatformConfigurationProvider().canVirtualizeLargeByteArrayAccess();
|
||||
}
|
||||
}
|
||||
|
117
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnschedulableGraphTest.java
Normal file
117
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnschedulableGraphTest.java
Normal file
@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
|
||||
package org.graalvm.compiler.core.test;
|
||||
|
||||
import static org.graalvm.compiler.debug.DebugOptions.DumpOnError;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.graalvm.compiler.api.directives.GraalDirectives;
|
||||
import org.graalvm.compiler.core.common.cfg.BlockMap;
|
||||
import org.graalvm.compiler.debug.DebugCloseable;
|
||||
import org.graalvm.compiler.debug.DebugContext;
|
||||
import org.graalvm.compiler.debug.TTY;
|
||||
import org.graalvm.compiler.graph.Node;
|
||||
import org.graalvm.compiler.graph.NodeMap;
|
||||
import org.graalvm.compiler.nodes.StructuredGraph;
|
||||
import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult;
|
||||
import org.graalvm.compiler.nodes.calc.NegateNode;
|
||||
import org.graalvm.compiler.nodes.cfg.Block;
|
||||
import org.graalvm.compiler.nodes.extended.OpaqueNode;
|
||||
import org.graalvm.compiler.options.OptionValues;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||
|
||||
/**
|
||||
* This test verifies that the backend detects graphs for which the scheduling is broken, i.e. input
|
||||
* values are scheduled in non-dominating blocks causing illegal flow of values in the control flow
|
||||
* graph.
|
||||
*/
|
||||
public class UnschedulableGraphTest extends GraalCompilerTest {
|
||||
|
||||
public static int snippet01(int a, int b, int c) {
|
||||
if (GraalDirectives.sideEffect(a) == b) {
|
||||
GraalDirectives.sideEffect(b);
|
||||
GraalDirectives.controlFlowAnchor();
|
||||
} else {
|
||||
GraalDirectives.sideEffect(c);
|
||||
GraalDirectives.controlFlowAnchor();
|
||||
}
|
||||
GraalDirectives.sideEffect();
|
||||
GraalDirectives.controlFlowAnchor();
|
||||
return GraalDirectives.opaque(-a) + GraalDirectives.opaque(-b);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void checkLowTierGraph(StructuredGraph graph) {
|
||||
super.checkLowTierGraph(graph);
|
||||
ScheduleResult res = graph.getLastSchedule();
|
||||
BlockMap<List<Node>> blockToNode = res.getBlockToNodesMap();
|
||||
NodeMap<Block> nodeToBlock = res.getNodeToBlockMap();
|
||||
Assert.assertEquals(4, res.getCFG().getBlocks().length);
|
||||
Block split = res.getCFG().getStartBlock();
|
||||
Assert.assertEquals(2, split.getSuccessorCount());
|
||||
Block trueSucc = split.getSuccessors()[0];
|
||||
Block falseSucc = split.getSuccessors()[1];
|
||||
Block merge = trueSucc.getFirstSuccessor();
|
||||
Assert.assertEquals(merge, falseSucc.getFirstSuccessor());
|
||||
for (OpaqueNode op : graph.getNodes().filter(OpaqueNode.class)) {
|
||||
Assert.assertEquals(merge, res.getNodeToBlockMap().get(op));
|
||||
}
|
||||
int k = 0;
|
||||
// destroy dominance relation for NegateNode nodes, they no longer dominate the addition
|
||||
for (NegateNode op : graph.getNodes().filter(NegateNode.class)) {
|
||||
final Block nonDominatingBlock = k++ % 2 == 0 ? trueSucc : falseSucc;
|
||||
blockToNode.get(merge).remove(op);
|
||||
blockToNode.get(nonDominatingBlock).add(0, op);
|
||||
nodeToBlock.set(op, nonDominatingBlock);
|
||||
}
|
||||
graph.getDebug().dump(DebugContext.VERBOSE_LEVEL, graph, "After changing constant schedule");
|
||||
}
|
||||
|
||||
private DebugContext getDebugContext(ResolvedJavaMethod method) {
|
||||
OptionValues options = new OptionValues(getInitialOptions(), DumpOnError, false);
|
||||
return getDebugContext(options, null, method);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("try")
|
||||
public void test01() {
|
||||
ResolvedJavaMethod method = getResolvedJavaMethod("snippet01");
|
||||
try (AutoCloseable c = new TTY.Filter();
|
||||
DebugContext debug = getDebugContext(method);
|
||||
DebugCloseable s = debug.disableIntercept()) {
|
||||
test("snippet01", 0, 1, 2);
|
||||
Assert.fail("Compilation should not reach this point, must throw an exception before");
|
||||
} catch (Throwable t) {
|
||||
if (t.getMessage().contains("liveIn set of first block must be empty")) {
|
||||
return;
|
||||
}
|
||||
throw new AssertionError(t);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -33,8 +33,8 @@ import org.graalvm.compiler.api.test.Graal;
|
||||
import org.graalvm.compiler.core.common.PermanentBailoutException;
|
||||
import org.graalvm.compiler.core.common.RetryableBailoutException;
|
||||
import org.graalvm.compiler.debug.DebugCloseable;
|
||||
import org.graalvm.compiler.debug.DebugHandlersFactory;
|
||||
import org.graalvm.compiler.debug.DebugContext;
|
||||
import org.graalvm.compiler.debug.DebugContext.Builder;
|
||||
import org.graalvm.compiler.debug.GraalError;
|
||||
import org.graalvm.compiler.java.GraphBuilderPhase;
|
||||
import org.graalvm.compiler.nodes.StructuredGraph;
|
||||
@ -128,7 +128,7 @@ public class VerifyBailoutUsageTest {
|
||||
graphBuilderSuite.appendPhase(new GraphBuilderPhase(config));
|
||||
HighTierContext context = new HighTierContext(providers, graphBuilderSuite, OptimisticOptimizations.NONE);
|
||||
OptionValues options = getInitialOptions();
|
||||
DebugContext debug = DebugContext.create(options, DebugHandlersFactory.LOADER);
|
||||
DebugContext debug = new Builder(options).build();
|
||||
for (Method m : c.getDeclaredMethods()) {
|
||||
if (!Modifier.isNative(m.getModifiers()) && !Modifier.isAbstract(m.getModifiers())) {
|
||||
ResolvedJavaMethod method = metaAccess.lookupJavaMethod(m);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2020, 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
|
||||
@ -144,8 +144,8 @@ public class VerifyDebugUsage extends VerifyPhase<CoreProviders> {
|
||||
"org.graalvm.compiler.phases.BasePhase.dumpAfter",
|
||||
"org.graalvm.compiler.phases.BasePhase.dumpBefore",
|
||||
"org.graalvm.compiler.core.GraalCompiler.emitFrontEnd",
|
||||
"org.graalvm.compiler.truffle.compiler.PartialEvaluator.fastPartialEvaluation",
|
||||
"org.graalvm.compiler.truffle.compiler.PartialEvaluator$PerformanceInformationHandler.reportPerformanceWarnings",
|
||||
"org.graalvm.compiler.truffle.compiler.PartialEvaluator.inliningGraphPE",
|
||||
"org.graalvm.compiler.truffle.compiler.PerformanceInformationHandler.reportPerformanceWarnings",
|
||||
"org.graalvm.compiler.truffle.compiler.TruffleCompilerImpl.compilePEGraph",
|
||||
"org.graalvm.compiler.core.test.VerifyDebugUsageTest$ValidDumpUsagePhase.run",
|
||||
"org.graalvm.compiler.core.test.VerifyDebugUsageTest$InvalidConcatDumpUsagePhase.run",
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2020, 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
|
||||
@ -31,8 +31,8 @@ import java.lang.reflect.Modifier;
|
||||
|
||||
import org.graalvm.compiler.api.test.Graal;
|
||||
import org.graalvm.compiler.debug.DebugCloseable;
|
||||
import org.graalvm.compiler.debug.DebugHandlersFactory;
|
||||
import org.graalvm.compiler.debug.DebugContext;
|
||||
import org.graalvm.compiler.debug.DebugContext.Builder;
|
||||
import org.graalvm.compiler.debug.GraalError;
|
||||
import org.graalvm.compiler.debug.Indent;
|
||||
import org.graalvm.compiler.graph.Node;
|
||||
@ -349,7 +349,7 @@ public class VerifyDebugUsageTest {
|
||||
graphBuilderSuite.appendPhase(new GraphBuilderPhase(config));
|
||||
HighTierContext context = new HighTierContext(providers, graphBuilderSuite, OptimisticOptimizations.NONE);
|
||||
OptionValues options = getInitialOptions();
|
||||
DebugContext debug = DebugContext.create(options, DebugHandlersFactory.LOADER);
|
||||
DebugContext debug = new Builder(options).build();
|
||||
for (Method m : c.getDeclaredMethods()) {
|
||||
if (!Modifier.isNative(m.getModifiers()) && !Modifier.isAbstract(m.getModifiers())) {
|
||||
ResolvedJavaMethod method = metaAccess.lookupJavaMethod(m);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2020, 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
|
||||
@ -34,8 +34,8 @@ import java.lang.reflect.Modifier;
|
||||
import org.graalvm.compiler.api.test.Graal;
|
||||
import org.graalvm.compiler.core.common.type.StampFactory;
|
||||
import org.graalvm.compiler.debug.DebugCloseable;
|
||||
import org.graalvm.compiler.debug.DebugHandlersFactory;
|
||||
import org.graalvm.compiler.debug.DebugContext;
|
||||
import org.graalvm.compiler.debug.DebugContext.Builder;
|
||||
import org.graalvm.compiler.graph.NodeClass;
|
||||
import org.graalvm.compiler.java.GraphBuilderPhase;
|
||||
import org.graalvm.compiler.nodeinfo.NodeInfo;
|
||||
@ -273,7 +273,7 @@ public class VerifyVirtualizableTest {
|
||||
graphBuilderSuite.appendPhase(new GraphBuilderPhase(config));
|
||||
HighTierContext context = new HighTierContext(providers, graphBuilderSuite, OptimisticOptimizations.NONE);
|
||||
OptionValues options = getInitialOptions();
|
||||
DebugContext debug = DebugContext.create(options, DebugHandlersFactory.LOADER);
|
||||
DebugContext debug = new Builder(options).build();
|
||||
for (Method m : c.getDeclaredMethods()) {
|
||||
if (!Modifier.isNative(m.getModifiers()) && !Modifier.isAbstract(m.getModifiers())) {
|
||||
ResolvedJavaMethod method = metaAccess.lookupJavaMethod(m);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -26,14 +26,9 @@ package org.graalvm.compiler.core.test.ea;
|
||||
|
||||
import java.lang.ref.SoftReference;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.graalvm.compiler.api.directives.GraalDirectives;
|
||||
import org.graalvm.compiler.core.test.TypeSystemTest;
|
||||
import org.graalvm.compiler.graph.Node;
|
||||
import org.graalvm.compiler.nodes.AbstractMergeNode;
|
||||
import org.graalvm.compiler.nodes.ReturnNode;
|
||||
import org.graalvm.compiler.nodes.cfg.ControlFlowGraph;
|
||||
import org.graalvm.compiler.nodes.extended.BoxNode;
|
||||
@ -45,6 +40,9 @@ import org.graalvm.compiler.nodes.java.NewInstanceNode;
|
||||
import org.graalvm.compiler.nodes.java.StoreFieldNode;
|
||||
import org.graalvm.compiler.nodes.virtual.CommitAllocationNode;
|
||||
import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* The PartialEscapeAnalysisPhase is expected to remove all allocations and return the correct
|
||||
@ -282,9 +280,7 @@ public class PartialEscapeAnalysisTest extends EATestBase {
|
||||
@SafeVarargs
|
||||
protected final void testPartialEscapeAnalysis(String snippet, double expectedProbability, int expectedCount, Class<? extends Node>... invalidNodeClasses) {
|
||||
prepareGraph(snippet, false);
|
||||
for (AbstractMergeNode merge : graph.getNodes(AbstractMergeNode.TYPE)) {
|
||||
merge.setStateAfter(null);
|
||||
}
|
||||
graph.clearAllStateAfter();
|
||||
new DeadCodeEliminationPhase().apply(graph);
|
||||
createCanonicalizerPhase().apply(graph, context);
|
||||
try {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2020, 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
|
||||
@ -34,8 +34,8 @@ import org.graalvm.compiler.code.CompilationResult;
|
||||
import org.graalvm.compiler.core.GraalCompiler;
|
||||
import org.graalvm.compiler.core.common.CompilationIdentifier;
|
||||
import org.graalvm.compiler.core.target.Backend;
|
||||
import org.graalvm.compiler.debug.DebugHandlersFactory;
|
||||
import org.graalvm.compiler.debug.DebugContext;
|
||||
import org.graalvm.compiler.debug.DebugContext.Builder;
|
||||
import org.graalvm.compiler.debug.DebugDumpScope;
|
||||
import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory;
|
||||
import org.graalvm.compiler.lir.phases.LIRSuites;
|
||||
@ -88,7 +88,7 @@ public class InvokeGraal {
|
||||
/* Create a unique compilation identifier, visible in IGV. */
|
||||
CompilationIdentifier compilationId = backend.getCompilationIdentifier(method);
|
||||
OptionValues options = getInitialOptions();
|
||||
DebugContext debug = DebugContext.create(options, DebugHandlersFactory.LOADER);
|
||||
DebugContext debug = new Builder(options).build();
|
||||
try (DebugContext.Scope s = debug.scope("compileAndInstallMethod", new DebugDumpScope(String.valueOf(compilationId), true))) {
|
||||
|
||||
/*
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -35,7 +35,7 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.graalvm.compiler.debug.DebugContext;
|
||||
import org.graalvm.compiler.debug.DebugHandlersFactory;
|
||||
import org.graalvm.compiler.debug.DebugContext.Builder;
|
||||
import org.graalvm.compiler.debug.GraalError;
|
||||
import org.graalvm.compiler.graph.Node;
|
||||
import org.graalvm.compiler.graph.NodeMap;
|
||||
@ -246,7 +246,7 @@ public class StaticAnalysis {
|
||||
*/
|
||||
|
||||
OptionValues options = getInitialOptions();
|
||||
DebugContext debug = DebugContext.create(options, DebugHandlersFactory.LOADER);
|
||||
DebugContext debug = new Builder(options).build();
|
||||
StructuredGraph graph = new StructuredGraph.Builder(options, debug).method(method).build();
|
||||
/*
|
||||
* Support for graph dumping, IGV uses this information to show the method name of a
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2020, 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
|
||||
@ -30,7 +30,6 @@ import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationFailureA
|
||||
import static org.graalvm.compiler.core.GraalCompilerOptions.ExitVMOnException;
|
||||
import static org.graalvm.compiler.core.GraalCompilerOptions.MaxCompilationProblemsPerAction;
|
||||
import static org.graalvm.compiler.core.common.GraalOptions.TrackNodeSourcePosition;
|
||||
import static org.graalvm.compiler.debug.DebugContext.VERBOSE_LEVEL;
|
||||
import static org.graalvm.compiler.debug.DebugOptions.Dump;
|
||||
import static org.graalvm.compiler.debug.DebugOptions.DumpPath;
|
||||
import static org.graalvm.compiler.debug.DebugOptions.MethodFilter;
|
||||
@ -43,6 +42,7 @@ import java.io.PrintStream;
|
||||
import java.util.Map;
|
||||
|
||||
import org.graalvm.compiler.debug.DebugContext;
|
||||
import org.graalvm.compiler.debug.DebugOptions;
|
||||
import org.graalvm.compiler.debug.DiagnosticsOutputDirectory;
|
||||
import org.graalvm.compiler.debug.PathUtilities;
|
||||
import org.graalvm.compiler.debug.TTY;
|
||||
@ -276,7 +276,7 @@ public abstract class CompilationWrapper<T> {
|
||||
}
|
||||
|
||||
OptionValues retryOptions = new OptionValues(initialOptions,
|
||||
Dump, ":" + VERBOSE_LEVEL,
|
||||
Dump, ":" + DebugOptions.DiagnoseDumpLevel.getValue(initialOptions),
|
||||
MethodFilter, null,
|
||||
DumpPath, dumpPath.getPath(),
|
||||
TrackNodeSourcePosition, true);
|
||||
|
@ -31,6 +31,7 @@ import org.graalvm.compiler.core.common.util.CompilationAlarm;
|
||||
import org.graalvm.compiler.core.target.Backend;
|
||||
import org.graalvm.compiler.debug.DebugCloseable;
|
||||
import org.graalvm.compiler.debug.DebugContext;
|
||||
import org.graalvm.compiler.debug.DebugContext.CompilerPhaseScope;
|
||||
import org.graalvm.compiler.debug.MethodFilter;
|
||||
import org.graalvm.compiler.debug.TimerKey;
|
||||
import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory;
|
||||
@ -208,9 +209,11 @@ public class GraalCompiler {
|
||||
try (DebugContext.Scope s = debug.scope("FrontEnd"); DebugCloseable a = FrontEnd.start(debug)) {
|
||||
HighTierContext highTierContext = new HighTierContext(providers, graphBuilderSuite, optimisticOpts);
|
||||
if (graph.start().next() == null) {
|
||||
graphBuilderSuite.apply(graph, highTierContext);
|
||||
new DeadCodeEliminationPhase(DeadCodeEliminationPhase.Optionality.Optional).apply(graph);
|
||||
debug.dump(DebugContext.BASIC_LEVEL, graph, "After parsing");
|
||||
try (CompilerPhaseScope cps = debug.enterCompilerPhase("Parsing")) {
|
||||
graphBuilderSuite.apply(graph, highTierContext);
|
||||
new DeadCodeEliminationPhase(DeadCodeEliminationPhase.Optionality.Optional).apply(graph);
|
||||
debug.dump(DebugContext.BASIC_LEVEL, graph, "After parsing");
|
||||
}
|
||||
} else {
|
||||
debug.dump(DebugContext.INFO_LEVEL, graph, "initial state");
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2020, 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
|
||||
@ -49,16 +49,16 @@ public class GraalServiceThread extends Thread {
|
||||
|
||||
/**
|
||||
* Substituted by {@code com.oracle.svm.graal.hotspot.libgraal.
|
||||
* Target_org_graalvm_compiler_truffle_common_TruffleCompilerRuntimeInstance} to attach to the
|
||||
* peer runtime if required.
|
||||
* Target_org_graalvm_compiler_core_GraalServiceThread} to attach to the peer runtime if
|
||||
* required.
|
||||
*/
|
||||
private void afterRun() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Substituted by {@code com.oracle.svm.graal.hotspot.libgraal.
|
||||
* Target_org_graalvm_compiler_truffle_common_TruffleCompilerRuntimeInstance} to attach to the
|
||||
* peer runtime if required.
|
||||
* Target_org_graalvm_compiler_core_GraalServiceThread} to attach to the peer runtime if
|
||||
* required.
|
||||
*/
|
||||
private void beforeRun() {
|
||||
}
|
||||
|
@ -1,6 +1,11 @@
|
||||
Specifies the action to take when compilation fails.
|
||||
|
||||
The accepted values are:
|
||||
Silent - Print nothing to the console.
|
||||
Print - Print a stack trace to the console.
|
||||
Diagnose - Retry the compilation with extra diagnostics.
|
||||
ExitVM - Same as Diagnose except that the VM process exits after retrying.
|
||||
Silent - Print nothing to the console.
|
||||
Print - Print a stack trace to the console.
|
||||
Diagnose* - Retry the compilation with extra diagnostics.
|
||||
ExitVM - Same as Diagnose except that the VM process exits after retrying.
|
||||
|
||||
* If "Diagnose" is set compilation will be retried with extra diagnostics enabled including dumping (see file:doc-files/DumpHelp.txt).
|
||||
In such a scenario DiagnoseDumpLevel can be used to specify the dump level (DebugContext dump levels) accordingly.
|
||||
|
@ -30,6 +30,7 @@ import java.util.Queue;
|
||||
|
||||
import jdk.internal.vm.compiler.collections.EconomicMap;
|
||||
import jdk.internal.vm.compiler.collections.Equivalence;
|
||||
import org.graalvm.compiler.core.common.spi.MetaAccessExtensionProvider;
|
||||
import org.graalvm.compiler.debug.CounterKey;
|
||||
import org.graalvm.compiler.debug.DebugContext;
|
||||
import org.graalvm.compiler.debug.GraalError;
|
||||
@ -66,10 +67,12 @@ import jdk.vm.ci.meta.Value;
|
||||
public class DebugInfoBuilder {
|
||||
|
||||
protected final NodeValueMap nodeValueMap;
|
||||
protected final MetaAccessExtensionProvider metaAccessExtensionProvider;
|
||||
protected final DebugContext debug;
|
||||
|
||||
public DebugInfoBuilder(NodeValueMap nodeValueMap, DebugContext debug) {
|
||||
public DebugInfoBuilder(NodeValueMap nodeValueMap, MetaAccessExtensionProvider metaAccessExtensionProvider, DebugContext debug) {
|
||||
this.nodeValueMap = nodeValueMap;
|
||||
this.metaAccessExtensionProvider = metaAccessExtensionProvider;
|
||||
this.debug = debug;
|
||||
}
|
||||
|
||||
@ -129,7 +132,7 @@ public class DebugInfoBuilder {
|
||||
for (int i = 0; i < entryCount; i++) {
|
||||
ValueNode value = currentField.values().get(i);
|
||||
if (value == null) {
|
||||
JavaKind entryKind = vobjNode.entryKind(i);
|
||||
JavaKind entryKind = vobjNode.entryKind(metaAccessExtensionProvider, i);
|
||||
values[pos] = JavaConstant.defaultForKind(entryKind.getStackKind());
|
||||
slotKinds[pos] = entryKind.getStackKind();
|
||||
pos++;
|
||||
@ -140,9 +143,9 @@ public class DebugInfoBuilder {
|
||||
} else {
|
||||
assert value.getStackKind() == JavaKind.Illegal;
|
||||
ValueNode previousValue = currentField.values().get(i - 1);
|
||||
assert (previousValue != null && (previousValue.getStackKind().needsTwoSlots()) || vobjNode.isVirtualByteArray()) : vobjNode + " " + i +
|
||||
assert (previousValue != null && (previousValue.getStackKind().needsTwoSlots()) || vobjNode.isVirtualByteArray(metaAccessExtensionProvider)) : vobjNode + " " + i +
|
||||
" " + previousValue + " " + currentField.values().snapshot();
|
||||
if (vobjNode.isVirtualByteArray()) {
|
||||
if (vobjNode.isVirtualByteArray(metaAccessExtensionProvider)) {
|
||||
/*
|
||||
* Let Illegals pass through to help knowing the number of bytes to
|
||||
* write. For example, writing a short to index 2 of a byte array of
|
||||
@ -158,7 +161,7 @@ public class DebugInfoBuilder {
|
||||
pos++;
|
||||
} else if (previousValue == null || !previousValue.getStackKind().needsTwoSlots()) {
|
||||
// Don't allow the IllegalConstant to leak into the debug info
|
||||
JavaKind entryKind = vobjNode.entryKind(i);
|
||||
JavaKind entryKind = vobjNode.entryKind(metaAccessExtensionProvider, i);
|
||||
values[pos] = JavaConstant.defaultForKind(entryKind.getStackKind());
|
||||
slotKinds[pos] = entryKind.getStackKind();
|
||||
pos++;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2020, 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
|
||||
@ -39,6 +39,7 @@ import org.graalvm.compiler.core.target.Backend;
|
||||
import org.graalvm.compiler.debug.CounterKey;
|
||||
import org.graalvm.compiler.debug.DebugCloseable;
|
||||
import org.graalvm.compiler.debug.DebugContext;
|
||||
import org.graalvm.compiler.debug.DebugContext.CompilerPhaseScope;
|
||||
import org.graalvm.compiler.debug.GraalError;
|
||||
import org.graalvm.compiler.debug.TimerKey;
|
||||
import org.graalvm.compiler.lir.LIR;
|
||||
@ -200,7 +201,7 @@ public class LIRCompilerBackend {
|
||||
ResolvedJavaMethod installedCodeOwner,
|
||||
CompilationResultBuilderFactory factory) {
|
||||
DebugContext debug = lirGenRes.getLIR().getDebug();
|
||||
try (DebugCloseable a = EmitCode.start(debug)) {
|
||||
try (DebugCloseable a = EmitCode.start(debug); CompilerPhaseScope cps = debug.enterCompilerPhase("Emit code");) {
|
||||
LIRGenerationProvider lirBackend = (LIRGenerationProvider) backend;
|
||||
|
||||
FrameMap frameMap = lirGenRes.getFrameMap();
|
||||
|
@ -43,6 +43,7 @@ import org.graalvm.compiler.core.common.LIRKind;
|
||||
import org.graalvm.compiler.core.common.calc.Condition;
|
||||
import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
|
||||
import org.graalvm.compiler.core.common.cfg.BlockMap;
|
||||
import org.graalvm.compiler.core.common.spi.ForeignCallLinkage;
|
||||
import org.graalvm.compiler.core.common.type.Stamp;
|
||||
import org.graalvm.compiler.core.match.ComplexMatchValue;
|
||||
import org.graalvm.compiler.core.match.MatchPattern;
|
||||
@ -99,6 +100,8 @@ import org.graalvm.compiler.nodes.calc.IntegerTestNode;
|
||||
import org.graalvm.compiler.nodes.calc.IsNullNode;
|
||||
import org.graalvm.compiler.nodes.cfg.Block;
|
||||
import org.graalvm.compiler.nodes.cfg.ControlFlowGraph;
|
||||
import org.graalvm.compiler.nodes.extended.ForeignCall;
|
||||
import org.graalvm.compiler.nodes.extended.ForeignCallWithExceptionNode;
|
||||
import org.graalvm.compiler.nodes.extended.IntegerSwitchNode;
|
||||
import org.graalvm.compiler.nodes.extended.SwitchNode;
|
||||
import org.graalvm.compiler.nodes.spi.LIRLowerable;
|
||||
@ -155,7 +158,7 @@ public abstract class NodeLIRBuilder implements NodeLIRBuilderTool, LIRGeneratio
|
||||
}
|
||||
|
||||
protected DebugInfoBuilder createDebugInfoBuilder(StructuredGraph graph, NodeValueMap nodeValueMap) {
|
||||
return new DebugInfoBuilder(nodeValueMap, graph.getDebug());
|
||||
return new DebugInfoBuilder(nodeValueMap, gen.getProviders().getMetaAccessExtensionProvider(), graph.getDebug());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -620,6 +623,28 @@ public abstract class NodeLIRBuilder implements NodeLIRBuilderTool, LIRGeneratio
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void emitForeignCall(ForeignCall x) {
|
||||
ForeignCallLinkage linkage = gen.getForeignCalls().lookupForeignCall(x.getDescriptor());
|
||||
|
||||
LabelRef exceptionEdge = null;
|
||||
if (x instanceof ForeignCallWithExceptionNode) {
|
||||
exceptionEdge = getLIRBlock(((ForeignCallWithExceptionNode) x).exceptionEdge());
|
||||
}
|
||||
LIRFrameState callState = stateWithExceptionEdge(x, exceptionEdge);
|
||||
|
||||
Value[] args = x.operands(this);
|
||||
|
||||
Value result = gen.emitForeignCall(linkage, callState, args);
|
||||
if (result != null) {
|
||||
setResult(x.asNode(), result);
|
||||
}
|
||||
|
||||
if (x instanceof ForeignCallWithExceptionNode) {
|
||||
gen.emitJump(getLIRBlock(((ForeignCallWithExceptionNode) x).next()));
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState);
|
||||
|
||||
protected abstract void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState);
|
||||
@ -735,7 +760,7 @@ public abstract class NodeLIRBuilder implements NodeLIRBuilderTool, LIRGeneratio
|
||||
if (gen.needOnlyOopMaps()) {
|
||||
return new LIRFrameState(null, null, null);
|
||||
}
|
||||
assert state != null : deopt;
|
||||
assert state != null : "Deopt node=" + deopt + " needs a state ";
|
||||
return getDebugInfoBuilder().build(deopt, state, exceptionEdge);
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -24,7 +24,6 @@
|
||||
|
||||
package org.graalvm.compiler.core.phases;
|
||||
|
||||
import static org.graalvm.compiler.core.common.GraalOptions.LateMembars;
|
||||
import static org.graalvm.compiler.phases.common.DeadCodeEliminationPhase.Optionality.Required;
|
||||
|
||||
import org.graalvm.compiler.core.common.GraalOptions;
|
||||
@ -37,7 +36,6 @@ import org.graalvm.compiler.phases.common.CanonicalizerPhase;
|
||||
import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase;
|
||||
import org.graalvm.compiler.phases.common.ExpandLogicPhase;
|
||||
import org.graalvm.compiler.phases.common.FixReadsPhase;
|
||||
import org.graalvm.compiler.phases.common.InsertMembarsPhase;
|
||||
import org.graalvm.compiler.phases.common.LoweringPhase;
|
||||
import org.graalvm.compiler.phases.common.ProfileCompiledMethodsPhase;
|
||||
import org.graalvm.compiler.phases.common.PropagateDeoptimizeProbabilityPhase;
|
||||
@ -80,9 +78,6 @@ public class LowTier extends BaseTier<LowTierContext> {
|
||||
|
||||
appendPhase(new PropagateDeoptimizeProbabilityPhase());
|
||||
|
||||
if (LateMembars.getValue(options)) {
|
||||
appendPhase(new InsertMembarsPhase());
|
||||
}
|
||||
appendPhase(new SchedulePhase(SchedulePhase.SchedulingStrategy.LATEST_OUT_OF_LOOPS));
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2009, 2020, 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
|
||||
@ -30,7 +30,7 @@ import org.graalvm.compiler.code.CompilationResult;
|
||||
import org.graalvm.compiler.core.common.CompilationIdentifier;
|
||||
import org.graalvm.compiler.core.common.LIRKind;
|
||||
import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig;
|
||||
import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
|
||||
import org.graalvm.compiler.core.common.spi.ForeignCallSignature;
|
||||
import org.graalvm.compiler.core.common.spi.ForeignCallsProvider;
|
||||
import org.graalvm.compiler.core.gen.LIRCompilerBackend;
|
||||
import org.graalvm.compiler.debug.DebugContext;
|
||||
@ -63,8 +63,8 @@ public abstract class Backend implements TargetProvider, ValueKindFactory<LIRKin
|
||||
private final Providers providers;
|
||||
private final ArrayList<CodeInstallationTaskFactory> codeInstallationTaskFactories;
|
||||
|
||||
public static final ForeignCallDescriptor ARITHMETIC_FREM = new ForeignCallDescriptor("arithmeticFrem", float.class, float.class, float.class);
|
||||
public static final ForeignCallDescriptor ARITHMETIC_DREM = new ForeignCallDescriptor("arithmeticDrem", double.class, double.class, double.class);
|
||||
public static final ForeignCallSignature ARITHMETIC_FREM = new ForeignCallSignature("arithmeticFrem", float.class, float.class, float.class);
|
||||
public static final ForeignCallSignature ARITHMETIC_DREM = new ForeignCallSignature("arithmeticDrem", double.class, double.class, double.class);
|
||||
|
||||
protected Backend(Providers providers) {
|
||||
this.providers = providers;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -33,7 +33,6 @@ import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.PrintStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Formatter;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
@ -43,6 +42,7 @@ import org.graalvm.compiler.debug.Assertions;
|
||||
import org.graalvm.compiler.debug.CounterKey;
|
||||
import org.graalvm.compiler.debug.DebugCloseable;
|
||||
import org.graalvm.compiler.debug.DebugContext;
|
||||
import org.graalvm.compiler.debug.DebugContext.Builder;
|
||||
import org.graalvm.compiler.debug.DebugContext.Scope;
|
||||
import org.graalvm.compiler.debug.DebugDumpHandler;
|
||||
import org.graalvm.compiler.debug.DebugHandler;
|
||||
@ -80,7 +80,7 @@ public class DebugContextTest {
|
||||
};
|
||||
|
||||
DebugContext openDebugContext(OptionValues options) {
|
||||
return DebugContext.create(options, NO_DESCRIPTION, NO_GLOBAL_METRIC_VALUES, new PrintStream(logOutput), Collections.singletonList(handlers));
|
||||
return new Builder(options, handlers).logStream(new PrintStream(logOutput)).build();
|
||||
|
||||
}
|
||||
}
|
||||
@ -203,7 +203,7 @@ public class DebugContextTest {
|
||||
map.put(DebugOptions.DumpOnError, true);
|
||||
OptionValues options = new OptionValues(map);
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
DebugContext debug = DebugContext.create(options, NO_DESCRIPTION, NO_GLOBAL_METRIC_VALUES, new PrintStream(baos), DebugHandlersFactory.LOADER);
|
||||
DebugContext debug = new Builder(options).globalMetrics(NO_GLOBAL_METRIC_VALUES).description(NO_DESCRIPTION).logStream(new PrintStream(baos)).build();
|
||||
Exception e = new Exception("testEnabledSandbox");
|
||||
String scopeName = "";
|
||||
try {
|
||||
@ -233,7 +233,7 @@ public class DebugContextTest {
|
||||
map.put(DebugOptions.DumpOnError, true);
|
||||
OptionValues options = new OptionValues(map);
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
DebugContext debug = DebugContext.create(options, NO_DESCRIPTION, NO_GLOBAL_METRIC_VALUES, new PrintStream(baos), DebugHandlersFactory.LOADER);
|
||||
DebugContext debug = new Builder(options).globalMetrics(NO_GLOBAL_METRIC_VALUES).description(NO_DESCRIPTION).logStream(new PrintStream(baos)).build();
|
||||
Exception e = new Exception("testDisabledSandbox");
|
||||
try {
|
||||
// Test a disabled sandbox scope
|
||||
@ -263,7 +263,7 @@ public class DebugContextTest {
|
||||
// Configure with an option that enables counters
|
||||
map.put(DebugOptions.Counters, "");
|
||||
OptionValues options = new OptionValues(map);
|
||||
DebugContext debug = DebugContext.create(options, DebugHandlersFactory.LOADER);
|
||||
DebugContext debug = new Builder(options).build();
|
||||
CounterKey counter = DebugContext.counter("DebugContextTestCounter");
|
||||
AssertionError[] result = {null};
|
||||
Thread thread = new Thread() {
|
||||
@ -291,7 +291,7 @@ public class DebugContextTest {
|
||||
map.put(DebugOptions.DumpOnError, true);
|
||||
OptionValues options = new OptionValues(map);
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
DebugContext debug = DebugContext.create(options, NO_DESCRIPTION, NO_GLOBAL_METRIC_VALUES, new PrintStream(baos), DebugHandlersFactory.LOADER);
|
||||
DebugContext debug = new Builder(options).globalMetrics(NO_GLOBAL_METRIC_VALUES).description(NO_DESCRIPTION).logStream(new PrintStream(baos)).build();
|
||||
Exception e = new Exception();
|
||||
try {
|
||||
try (DebugCloseable disabled = debug.disableIntercept(); Scope s1 = debug.scope("ScopeWithDisabledIntercept")) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -24,15 +24,13 @@
|
||||
|
||||
package org.graalvm.compiler.debug.test;
|
||||
|
||||
import static org.graalvm.compiler.debug.DebugContext.DEFAULT_LOG_STREAM;
|
||||
import static org.graalvm.compiler.debug.DebugContext.NO_CONFIG_CUSTOMIZERS;
|
||||
import static org.graalvm.compiler.debug.DebugContext.NO_DESCRIPTION;
|
||||
import static org.graalvm.compiler.debug.DebugContext.NO_GLOBAL_METRIC_VALUES;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import jdk.internal.vm.compiler.collections.EconomicMap;
|
||||
import org.graalvm.compiler.debug.DebugCloseable;
|
||||
import org.graalvm.compiler.debug.DebugContext;
|
||||
import org.graalvm.compiler.debug.DebugContext.Builder;
|
||||
import org.graalvm.compiler.debug.DebugOptions;
|
||||
import org.graalvm.compiler.debug.TimerKey;
|
||||
import org.graalvm.compiler.options.OptionKey;
|
||||
@ -88,7 +86,7 @@ public class TimerKeyTest {
|
||||
EconomicMap<OptionKey<?>, Object> map = EconomicMap.create();
|
||||
map.put(DebugOptions.Time, "");
|
||||
OptionValues options = new OptionValues(map);
|
||||
DebugContext debug = DebugContext.create(options, NO_DESCRIPTION, NO_GLOBAL_METRIC_VALUES, DEFAULT_LOG_STREAM, NO_CONFIG_CUSTOMIZERS);
|
||||
DebugContext debug = new Builder(options, NO_CONFIG_CUSTOMIZERS).build();
|
||||
|
||||
TimerKey timerC = DebugContext.timer("TimerC");
|
||||
try (DebugCloseable c1 = timerC.start(debug)) {
|
||||
|
57
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/CompilationListener.java
Normal file
57
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/CompilationListener.java
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (c) 2020, 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.debug;
|
||||
|
||||
import org.graalvm.compiler.debug.DebugContext.CompilerPhaseScope;
|
||||
|
||||
import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||
|
||||
/**
|
||||
* Implemented by clients interested in when the compiler starts/ends a {@linkplain #enterPhase
|
||||
* phase} or {@linkplain #notifyInlining considers inlining} a method.
|
||||
*/
|
||||
public interface CompilationListener {
|
||||
|
||||
/**
|
||||
* Notifies this listener that the compiler is starting a compiler phase.
|
||||
*
|
||||
* @param name the name of the phase
|
||||
* @return an object whose {@link CompilerPhaseScope#close()} method will be called when the
|
||||
* phase completes
|
||||
*/
|
||||
CompilerPhaseScope enterPhase(CharSequence name, int nesting);
|
||||
|
||||
/**
|
||||
* Notifies this listener when the compiler considers inlining {@code callee} into
|
||||
* {@code caller}.
|
||||
*
|
||||
* @param caller caller method
|
||||
* @param callee callee method considered for inlining into {@code caller}
|
||||
* @param succeeded true if {@code callee} was inlined into {@code caller}
|
||||
* @param message extra information about inlining decision
|
||||
* @param bci byte code index of call site
|
||||
*/
|
||||
void notifyInlining(ResolvedJavaMethod caller, ResolvedJavaMethod callee, boolean succeeded, CharSequence message, int bci);
|
||||
}
|
@ -59,6 +59,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.SortedMap;
|
||||
import java.util.TreeMap;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import jdk.internal.vm.compiler.collections.EconomicMap;
|
||||
import jdk.internal.vm.compiler.collections.EconomicSet;
|
||||
@ -68,7 +69,9 @@ import org.graalvm.compiler.options.OptionValues;
|
||||
import org.graalvm.compiler.serviceprovider.GraalServices;
|
||||
import org.graalvm.graphio.GraphOutput;
|
||||
|
||||
import jdk.vm.ci.common.NativeImageReinitialize;
|
||||
import jdk.vm.ci.meta.JavaMethod;
|
||||
import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||
|
||||
/**
|
||||
* A facility for logging and dumping as well as a container for values associated with
|
||||
@ -86,8 +89,6 @@ public final class DebugContext implements AutoCloseable {
|
||||
public static final GlobalMetrics NO_GLOBAL_METRIC_VALUES = null;
|
||||
public static final Iterable<DebugHandlersFactory> NO_CONFIG_CUSTOMIZERS = Collections.emptyList();
|
||||
|
||||
public static final PrintStream DEFAULT_LOG_STREAM = TTY.out;
|
||||
|
||||
/**
|
||||
* Contains the immutable parts of a debug context. This separation allows the immutable parts
|
||||
* to be shared and reduces the overhead of initialization since most immutable fields are
|
||||
@ -114,6 +115,10 @@ public final class DebugContext implements AutoCloseable {
|
||||
*/
|
||||
private long[] metricValues;
|
||||
|
||||
public static PrintStream getDefaultLogStream() {
|
||||
return TTY.out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if dynamic scopes are enabled.
|
||||
*/
|
||||
@ -128,6 +133,7 @@ public final class DebugContext implements AutoCloseable {
|
||||
if (sharedChannel == null) {
|
||||
sharedChannel = new IgvDumpChannel(() -> getDumpPath(".bgv", false), immutable.options);
|
||||
}
|
||||
builder.attr(GraphOutput.ATTR_VM_ID, GraalServices.getExecutionID());
|
||||
final GraphOutput<G, M> output = builder.build(sharedChannel);
|
||||
parentOutput = output;
|
||||
return output;
|
||||
@ -315,7 +321,7 @@ public final class DebugContext implements AutoCloseable {
|
||||
/**
|
||||
* Singleton used to represent a disabled debug context.
|
||||
*/
|
||||
private static final DebugContext DISABLED = new DebugContext(NO_DESCRIPTION, NO_GLOBAL_METRIC_VALUES, DEFAULT_LOG_STREAM, new Immutable(), NO_CONFIG_CUSTOMIZERS);
|
||||
private static final DebugContext DISABLED = new DebugContext(NO_DESCRIPTION, null, NO_GLOBAL_METRIC_VALUES, getDefaultLogStream(), new Immutable(), NO_CONFIG_CUSTOMIZERS);
|
||||
|
||||
/**
|
||||
* Create a DebugContext with debugging disabled.
|
||||
@ -324,7 +330,7 @@ public final class DebugContext implements AutoCloseable {
|
||||
if (options == null || options.getMap().isEmpty()) {
|
||||
return DISABLED;
|
||||
}
|
||||
return new DebugContext(NO_DESCRIPTION, NO_GLOBAL_METRIC_VALUES, DEFAULT_LOG_STREAM, Immutable.create(options), NO_CONFIG_CUSTOMIZERS);
|
||||
return new DebugContext(NO_DESCRIPTION, null, NO_GLOBAL_METRIC_VALUES, getDefaultLogStream(), Immutable.create(options), NO_CONFIG_CUSTOMIZERS);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -377,6 +383,8 @@ public final class DebugContext implements AutoCloseable {
|
||||
|
||||
private final Description description;
|
||||
|
||||
private final CompilationListener compilationListener;
|
||||
|
||||
/**
|
||||
* Gets a description of the computation associated with this debug context.
|
||||
*
|
||||
@ -386,6 +394,89 @@ public final class DebugContext implements AutoCloseable {
|
||||
return description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if {@link #enterCompilerPhase} and {@link #notifyInlining} do anything.
|
||||
*
|
||||
* @return {@code true} if there is a listener for compiler phase and inlining events attached
|
||||
* to this object, {@code false} otherwise
|
||||
*/
|
||||
public boolean hasCompilationListener() {
|
||||
return compilationListener != null;
|
||||
}
|
||||
|
||||
private int compilerPhaseNesting = 0;
|
||||
|
||||
/**
|
||||
* Scope for a compiler phase event.
|
||||
*/
|
||||
public interface CompilerPhaseScope extends AutoCloseable {
|
||||
/**
|
||||
* Notifies the listener that the phase has ended.
|
||||
*/
|
||||
@Override
|
||||
void close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies this object that the compiler is entering a phase.
|
||||
*
|
||||
* It is recommended to use this method in a try-with-resource statement.
|
||||
*
|
||||
* @param phaseName name of the phase being entered
|
||||
* @return {@code null} if {@link #hasCompilationListener()} returns {@code false} otherwise an
|
||||
* object whose {@link CompilerPhaseScope#close()} method must be called when the phase
|
||||
* ends
|
||||
*/
|
||||
public CompilerPhaseScope enterCompilerPhase(CharSequence phaseName) {
|
||||
if (compilationListener != null) {
|
||||
return enterCompilerPhase(() -> phaseName);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies this object that the compiler is entering a phase.
|
||||
*
|
||||
* It is recommended to use this method in a try-with-resource statement.
|
||||
*
|
||||
* @param phaseName name of the phase being entered
|
||||
* @return {@code null} if {@link #hasCompilationListener()} returns {@code false} otherwise an
|
||||
* object whose {@link CompilerPhaseScope#close()} method must be called when the phase
|
||||
* ends
|
||||
*/
|
||||
public CompilerPhaseScope enterCompilerPhase(Supplier<CharSequence> phaseName) {
|
||||
CompilationListener l = compilationListener;
|
||||
if (l != null) {
|
||||
CompilerPhaseScope scope = l.enterPhase(phaseName.get(), compilerPhaseNesting++);
|
||||
return new CompilerPhaseScope() {
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
--compilerPhaseNesting;
|
||||
scope.close();
|
||||
}
|
||||
};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies this object when the compiler considers inlining {@code callee} into {@code caller}.
|
||||
* A call to this method should be guarded with {@link #hasCompilationListener()} if
|
||||
* {@code message} is not a string literal or pre-computed value
|
||||
*
|
||||
* @param caller caller method
|
||||
* @param callee callee method considered for inlining into {@code caller}
|
||||
* @param succeeded true if {@code callee} was inlined into {@code caller}
|
||||
* @param message extra information about inlining decision
|
||||
* @param bci byte code index of call site
|
||||
*/
|
||||
public void notifyInlining(ResolvedJavaMethod caller, ResolvedJavaMethod callee, boolean succeeded, CharSequence message, int bci) {
|
||||
if (compilationListener != null) {
|
||||
compilationListener.notifyInlining(caller, callee, succeeded, message, bci);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the global metrics associated with this debug context.
|
||||
*
|
||||
@ -396,43 +487,91 @@ public final class DebugContext implements AutoCloseable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link DebugContext} based on a given set of option values and {@code factory}.
|
||||
* Object used to create a {@link DebugContext}.
|
||||
*/
|
||||
public static DebugContext create(OptionValues options, DebugHandlersFactory factory) {
|
||||
return new DebugContext(NO_DESCRIPTION, NO_GLOBAL_METRIC_VALUES, DEFAULT_LOG_STREAM, Immutable.create(options), Collections.singletonList(factory));
|
||||
public static class Builder {
|
||||
private final OptionValues options;
|
||||
private Description description = NO_DESCRIPTION;
|
||||
private CompilationListener compilationListener;
|
||||
private GlobalMetrics globalMetrics = NO_GLOBAL_METRIC_VALUES;
|
||||
private PrintStream logStream = getDefaultLogStream();
|
||||
private final Iterable<DebugHandlersFactory> factories;
|
||||
|
||||
/**
|
||||
* Builder for a {@link DebugContext} based on {@code options} and
|
||||
* {@link DebugHandlersFactory#LOADER}.
|
||||
*/
|
||||
public Builder(OptionValues options) {
|
||||
this.options = options;
|
||||
this.factories = DebugHandlersFactory.LOADER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder for a {@link DebugContext} based on {@code options} and {@code factories}. The
|
||||
* {@link DebugHandlersFactory#LOADER} value can be used for the latter.
|
||||
*/
|
||||
public Builder(OptionValues options, Iterable<DebugHandlersFactory> factories) {
|
||||
this.options = options;
|
||||
this.factories = factories;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder for a {@link DebugContext} based {@code options} and {@code factory}. The latter
|
||||
* can be null in which case {@link DebugContext#NO_CONFIG_CUSTOMIZERS} is used.
|
||||
*/
|
||||
public Builder(OptionValues options, DebugHandlersFactory factory) {
|
||||
this.options = options;
|
||||
this.factories = factory == null ? NO_CONFIG_CUSTOMIZERS : Collections.singletonList(factory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the description for the debug context. The default is for a context to have no
|
||||
* description.
|
||||
*/
|
||||
public Builder description(Description desc) {
|
||||
this.description = desc;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the compilation listener for the debug context. The default is for a context to have
|
||||
* no compilation listener.
|
||||
*/
|
||||
public Builder compilationListener(CompilationListener listener) {
|
||||
this.compilationListener = listener;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder globalMetrics(GlobalMetrics metrics) {
|
||||
this.globalMetrics = metrics;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder logStream(PrintStream stream) {
|
||||
this.logStream = stream;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DebugContext build() {
|
||||
return new DebugContext(description,
|
||||
compilationListener,
|
||||
globalMetrics,
|
||||
logStream,
|
||||
Immutable.create(options),
|
||||
factories);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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, Iterable<DebugHandlersFactory> 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}.
|
||||
*/
|
||||
public static DebugContext create(OptionValues options, Description description, GlobalMetrics globalMetrics, PrintStream logStream, Iterable<DebugHandlersFactory> factories) {
|
||||
return new DebugContext(description, globalMetrics, logStream, Immutable.create(options), factories);
|
||||
}
|
||||
|
||||
private DebugContext(Description description, GlobalMetrics globalMetrics, PrintStream logStream, Immutable immutable, Iterable<DebugHandlersFactory> factories) {
|
||||
private DebugContext(Description description,
|
||||
CompilationListener compilationListener,
|
||||
GlobalMetrics globalMetrics,
|
||||
PrintStream logStream,
|
||||
Immutable immutable,
|
||||
Iterable<DebugHandlersFactory> factories) {
|
||||
this.immutable = immutable;
|
||||
this.description = description;
|
||||
this.globalMetrics = globalMetrics;
|
||||
this.compilationListener = compilationListener;
|
||||
if (immutable.scopesEnabled) {
|
||||
OptionValues options = immutable.options;
|
||||
List<DebugDumpHandler> dumpHandlers = new ArrayList<>();
|
||||
@ -653,7 +792,11 @@ public final class DebugContext implements AutoCloseable {
|
||||
}
|
||||
}
|
||||
|
||||
private final Invariants invariants = Assertions.assertionsEnabled() ? new Invariants() : null;
|
||||
/**
|
||||
* Arbitrary threads cannot be in the image so null out {@code DebugContext.invariants} which
|
||||
* holds onto a thread and is only used for assertions.
|
||||
*/
|
||||
@NativeImageReinitialize private final Invariants invariants = Assertions.assertionsEnabled() ? new Invariants() : null;
|
||||
|
||||
static StackTraceElement[] getStackTrace(Thread thread) {
|
||||
return thread.getStackTrace();
|
||||
|
@ -115,13 +115,16 @@ public class DebugOptions {
|
||||
@Option(help = "file:doc-files/MetricsFileHelp.txt", type = OptionType.Debug)
|
||||
public static final OptionKey<String> MetricsFile = new OptionKey<>(null);
|
||||
@Option(help = "File to which aggregated metrics are dumped at shutdown. A CSV format is used if the file ends with .csv " +
|
||||
"otherwise a more human readable format is used. If not specified, metrics are dumped to the console.", type = OptionType.Debug)
|
||||
"otherwise a more human readable format is used. If not specified, metrics are dumped to the console.", type = OptionType.Debug)
|
||||
public static final OptionKey<String> AggregatedMetricsFile = new OptionKey<>(null);
|
||||
|
||||
@Option(help = "Enable debug output for stub code generation and snippet preparation.", type = OptionType.Debug)
|
||||
public static final OptionKey<Boolean> DebugStubsAndSnippets = new OptionKey<>(false);
|
||||
@Option(help = "Send compiler IR to dump handlers on error.", type = OptionType.Debug)
|
||||
public static final OptionKey<Boolean> DumpOnError = new OptionKey<>(false);
|
||||
@Option(help = "Specify the DumpLevel if CompilationFailureAction#Diagnose is used." +
|
||||
"See CompilationFailureAction for details. file:doc-files/CompilationFailureActionHelp.txt", type = OptionType.Debug)
|
||||
public static final OptionKey<Integer> DiagnoseDumpLevel = new OptionKey<>(DebugContext.VERBOSE_LEVEL);
|
||||
@Option(help = "Disable intercepting exceptions in debug scopes.", type = OptionType.Debug)
|
||||
public static final OptionKey<Boolean> DisableIntercept = new OptionKey<>(false);
|
||||
@Option(help = "Intercept also bailout exceptions", type = OptionType.Debug)
|
||||
@ -137,7 +140,9 @@ public class DebugOptions {
|
||||
@Option(help = "Enable dumping to the C1Visualizer. Enabling this option implies PrintBackendCFG.", type = OptionType.Debug)
|
||||
public static final OptionKey<Boolean> PrintCFG = new OptionKey<>(false);
|
||||
@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<>(false);
|
||||
@Option(help = "Enable dumping CFG built during initial BciBlockMapping", type = OptionType.Debug)
|
||||
public static final OptionKey<Boolean> PrintBlockMapping = new OptionKey<>(false);
|
||||
|
||||
@Option(help = "file:doc-files/PrintGraphHelp.txt", type = OptionType.Debug)
|
||||
public static final EnumOptionKey<PrintGraphTarget> PrintGraph = new EnumOptionKey<>(PrintGraphTarget.File);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2020, 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
|
||||
@ -42,6 +42,7 @@ import java.util.zip.ZipOutputStream;
|
||||
|
||||
import org.graalvm.compiler.options.OptionValues;
|
||||
import org.graalvm.compiler.serviceprovider.GraalServices;
|
||||
import org.graalvm.compiler.serviceprovider.IsolateUtil;
|
||||
|
||||
/**
|
||||
* Manages a directory into which diagnostics such crash reports and dumps should be written. The
|
||||
@ -107,7 +108,7 @@ public class DiagnosticsOutputDirectory {
|
||||
// directory specified by the DumpPath option.
|
||||
baseDir = Paths.get(".");
|
||||
}
|
||||
return baseDir.resolve("graal_diagnostics_" + GraalServices.getExecutionID()).toAbsolutePath().toString();
|
||||
return baseDir.resolve("graal_diagnostics_" + GraalServices.getExecutionID() + '@' + IsolateUtil.getIsolateID()).toAbsolutePath().toString();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2020, 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
|
||||
@ -27,6 +27,7 @@ package org.graalvm.compiler.debug;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@ -35,6 +36,7 @@ import jdk.internal.vm.compiler.collections.EconomicMap;
|
||||
import jdk.internal.vm.compiler.collections.MapCursor;
|
||||
import jdk.internal.vm.compiler.collections.Pair;
|
||||
import org.graalvm.compiler.options.OptionValues;
|
||||
import org.graalvm.compiler.serviceprovider.IsolateUtil;
|
||||
|
||||
/**
|
||||
* Metric values that can be {@linkplain #add(DebugContext) updated} by multiple threads.
|
||||
@ -75,10 +77,30 @@ public class GlobalMetrics {
|
||||
return res;
|
||||
}
|
||||
|
||||
private static PrintStream openPrintStream(String metricsFile) throws IOException {
|
||||
if (metricsFile == null) {
|
||||
return DebugContext.getDefaultLogStream();
|
||||
} else {
|
||||
long isolateID = IsolateUtil.getIsolateID();
|
||||
Path path;
|
||||
if (isolateID != 0L) {
|
||||
int lastDot = metricsFile.lastIndexOf('.');
|
||||
if (lastDot != -1) {
|
||||
path = Paths.get(metricsFile.substring(0, lastDot) + '@' + isolateID + metricsFile.substring(lastDot));
|
||||
} else {
|
||||
path = Paths.get(metricsFile + isolateID);
|
||||
}
|
||||
} else {
|
||||
path = Paths.get(metricsFile);
|
||||
}
|
||||
return new PrintStream(Files.newOutputStream(path));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the values in the object to the file specified by
|
||||
* {@link DebugOptions#AggregatedMetricsFile} if present otherwise to
|
||||
* {@link DebugContext#DEFAULT_LOG_STREAM}.
|
||||
* {@link DebugContext#getDefaultLogStream()}.
|
||||
*/
|
||||
public void print(OptionValues options) {
|
||||
long[] vals = values;
|
||||
@ -88,10 +110,11 @@ public class GlobalMetrics {
|
||||
boolean csv = metricsFile != null && (metricsFile.endsWith(".csv") || metricsFile.endsWith(".CSV"));
|
||||
PrintStream p = null;
|
||||
try {
|
||||
p = metricsFile == null ? DebugContext.DEFAULT_LOG_STREAM : new PrintStream(Files.newOutputStream(Paths.get(metricsFile)));
|
||||
p = openPrintStream(metricsFile);
|
||||
String isolateID = IsolateUtil.getIsolateID(false);
|
||||
if (!csv) {
|
||||
if (!map.isEmpty()) {
|
||||
p.println("++ Aggregated Metrics ++");
|
||||
p.printf("++ Aggregated Metrics %s ++%n", isolateID);
|
||||
}
|
||||
}
|
||||
String csvFormat = CSVUtil.buildFormatString("%s", "%s", "%s");
|
||||
@ -107,7 +130,7 @@ public class GlobalMetrics {
|
||||
}
|
||||
if (!csv) {
|
||||
if (!map.isEmpty()) {
|
||||
p.println("-- Aggregated Metrics --");
|
||||
p.printf("-- Aggregated Metrics %s --%n", isolateID);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2020, 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
|
||||
@ -25,8 +25,8 @@
|
||||
package org.graalvm.compiler.graph.test;
|
||||
|
||||
import org.graalvm.compiler.api.test.Graal;
|
||||
import org.graalvm.compiler.debug.DebugHandlersFactory;
|
||||
import org.graalvm.compiler.debug.DebugContext;
|
||||
import org.graalvm.compiler.debug.DebugContext.Builder;
|
||||
import org.graalvm.compiler.options.OptionValues;
|
||||
import org.junit.After;
|
||||
|
||||
@ -46,7 +46,7 @@ public abstract class GraphTest {
|
||||
}
|
||||
throw new AssertionError("At most one " + DebugContext.class.getName() + " object should be created per test");
|
||||
}
|
||||
DebugContext debug = DebugContext.create(options, DebugHandlersFactory.LOADER);
|
||||
DebugContext debug = new Builder(options).build();
|
||||
cachedDebug.set(debug);
|
||||
return debug;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2020, 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
|
||||
@ -44,6 +44,7 @@ import org.graalvm.graphio.GraphTypes;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import org.junit.Test;
|
||||
import java.lang.reflect.Field;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public final class GraphOutputTest {
|
||||
|
||||
@ -131,6 +132,96 @@ public final class GraphOutputTest {
|
||||
assertSame(CustomEnum.class, clazz);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings({"static-method", "unchecked"})
|
||||
public void testBuilderPromotesVersion() throws Exception {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
try (WritableByteChannel channel = Channels.newChannel(out)) {
|
||||
GraphOutput.Builder<MockGraph, Void, ?> builder = GraphOutput.newBuilder(new MockGraphStructure()).attr("test", "failed");
|
||||
try (GraphOutput<MockGraph, ?> graphOutput = builder.build(channel)) {
|
||||
graphOutput.print(new MockGraph(), Collections.emptyMap(), 0, "Mock Graph");
|
||||
} catch (IllegalStateException ise) {
|
||||
// expected exception
|
||||
}
|
||||
}
|
||||
byte[] bytes = out.toByteArray();
|
||||
// there's B-I-G-V, major, minor
|
||||
assertEquals("Major version 7 must be auto-selected", 7, bytes[4]);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings({"static-method", "unchecked"})
|
||||
public void testTooOldVersionFails() throws Exception {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
try (WritableByteChannel channel = Channels.newChannel(out)) {
|
||||
GraphOutput.Builder<MockGraph, Void, ?> builder = GraphOutput.newBuilder(new MockGraphStructure()).protocolVersion(6, 1);
|
||||
try {
|
||||
builder.attr("test", "failed");
|
||||
fail("Should have failed, attr() requires version 7.0");
|
||||
} catch (IllegalStateException ex) {
|
||||
// expected
|
||||
}
|
||||
try (GraphOutput<MockGraph, ?> graphOutput = builder.build(channel)) {
|
||||
graphOutput.print(new MockGraph(), Collections.emptyMap(), 0, "Mock Graph");
|
||||
} catch (IllegalStateException ise) {
|
||||
// expected exception
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings({"static-method", "unchecked"})
|
||||
public void testVersionDowngradeFails() throws Exception {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
try (WritableByteChannel channel = Channels.newChannel(out)) {
|
||||
GraphOutput.Builder<MockGraph, Void, ?> builder = GraphOutput.newBuilder(new MockGraphStructure());
|
||||
builder.attr("test", "failed");
|
||||
try {
|
||||
builder.protocolVersion(6, 0);
|
||||
fail("Should fail, cannot downgrade from required version.");
|
||||
} catch (IllegalArgumentException e) {
|
||||
// expected
|
||||
}
|
||||
try (GraphOutput<MockGraph, ?> graphOutput = builder.build(channel)) {
|
||||
graphOutput.print(new MockGraph(), Collections.emptyMap(), 0, "Mock Graph");
|
||||
} catch (IllegalStateException ise) {
|
||||
// expected exception
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings({"static-method", "unchecked"})
|
||||
public void testManualAncientVersion() throws Exception {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
try (WritableByteChannel channel = Channels.newChannel(out)) {
|
||||
GraphOutput.Builder<MockGraph, Void, ?> builder = GraphOutput.newBuilder(new MockGraphStructure()).protocolVersion(3, 0);
|
||||
try (GraphOutput<MockGraph, ?> graphOutput = builder.build(channel)) {
|
||||
graphOutput.print(new MockGraph(), Collections.emptyMap(), 0, "Mock Graph");
|
||||
}
|
||||
}
|
||||
byte[] bytes = out.toByteArray();
|
||||
// there's B-I-G-V, major, minor
|
||||
assertEquals("Protocol version 3 was requested", 3, bytes[4]);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings({"static-method", "unchecked"})
|
||||
public void testManualVersionUpgradeOK() throws Exception {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
try (WritableByteChannel channel = Channels.newChannel(out)) {
|
||||
GraphOutput.Builder<MockGraph, Void, ?> builder = GraphOutput.newBuilder(new MockGraphStructure());
|
||||
builder.attr("some", "thing");
|
||||
builder.protocolVersion(7, 0);
|
||||
try (GraphOutput<MockGraph, ?> graphOutput = builder.build(channel)) {
|
||||
graphOutput.print(new MockGraph(), Collections.emptyMap(), 0, "Mock Graph");
|
||||
}
|
||||
}
|
||||
byte[] bytes = out.toByteArray();
|
||||
// there's B-I-G-V, major, minor
|
||||
assertEquals("Protocol version 7 was requested", 7, bytes[4]);
|
||||
}
|
||||
|
||||
private static ByteBuffer generateData(int size) {
|
||||
ByteBuffer buffer = ByteBuffer.allocate(size);
|
||||
for (int i = 0; i < size; i++) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2020, 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
|
||||
@ -56,8 +56,8 @@ public final class NodeEncodingTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultVersionTheNodeIsntDumpedWithItsID() throws Exception {
|
||||
runTheNodeIsntDumpedWithItsID(false);
|
||||
public void defaultVersionTheNodeIsDumpedWithItsID() throws Exception {
|
||||
runTheNodeIsTreatedPoolEntry(false);
|
||||
}
|
||||
|
||||
private void runTheNodeIsntDumpedWithItsID(boolean explicitVersion) throws Exception {
|
||||
|
@ -427,12 +427,30 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface {
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether this node has exactly one usgae.
|
||||
* Checks whether this node has exactly one usage.
|
||||
*/
|
||||
public final boolean hasExactlyOneUsage() {
|
||||
return hasUsages() && !hasMoreThanOneUsage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether this node has only usages of that type.
|
||||
*
|
||||
* @param type the type of usages to look for
|
||||
*/
|
||||
public final boolean hasOnlyUsagesOfType(InputType type) {
|
||||
for (Node usage : usages()) {
|
||||
for (Position pos : usage.inputPositions()) {
|
||||
if (pos.get(usage) == this) {
|
||||
if (pos.getInputType() != type) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a given node to this node's {@linkplain #usages() usages}.
|
||||
*
|
||||
@ -858,7 +876,7 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface {
|
||||
}
|
||||
}
|
||||
|
||||
public void replaceAtUsages(InputType type, Node other) {
|
||||
public void replaceAtUsages(Node other, InputType type) {
|
||||
checkReplaceWith(other);
|
||||
int i = 0;
|
||||
int usageCount = this.getUsageCount();
|
||||
@ -882,6 +900,32 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface {
|
||||
}
|
||||
}
|
||||
|
||||
public void replaceAtUsages(Node other, InputType... inputTypes) {
|
||||
checkReplaceWith(other);
|
||||
int i = 0;
|
||||
int usageCount = this.getUsageCount();
|
||||
if (usageCount == 0) {
|
||||
return;
|
||||
}
|
||||
usages: while (i < usageCount) {
|
||||
Node usage = this.getUsageAt(i);
|
||||
for (Position pos : usage.inputPositions()) {
|
||||
for (InputType type : inputTypes) {
|
||||
if (pos.getInputType() == type && pos.get(usage) == this) {
|
||||
replaceAtUsagePos(other, usage, pos);
|
||||
this.movUsageFromEndTo(i);
|
||||
usageCount--;
|
||||
continue usages;
|
||||
}
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if (hasNoUsages()) {
|
||||
maybeNotifyZeroUsages(this);
|
||||
}
|
||||
}
|
||||
|
||||
private void maybeNotifyInputChanged(Node node) {
|
||||
if (graph != null) {
|
||||
assert !graph.isFrozen();
|
||||
|
@ -164,8 +164,8 @@ public final class NodeClass<T> extends FieldIntrospection<T> {
|
||||
private static final Class<?> INPUT_LIST_CLASS = NodeInputList.class;
|
||||
private static final Class<?> SUCCESSOR_LIST_CLASS = NodeSuccessorList.class;
|
||||
|
||||
private static AtomicInteger nextIterableId = new AtomicInteger();
|
||||
private static AtomicInteger nextLeafId = new AtomicInteger();
|
||||
private static final AtomicInteger nextIterableId = new AtomicInteger();
|
||||
private static final AtomicInteger nextLeafId = new AtomicInteger();
|
||||
|
||||
private final InputEdges inputs;
|
||||
private final SuccessorEdges successors;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2020, 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
|
||||
@ -31,10 +31,20 @@ import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.RandomAccess;
|
||||
|
||||
import org.graalvm.compiler.core.common.PermanentBailoutException;
|
||||
import org.graalvm.compiler.graph.iterators.NodeIterable;
|
||||
|
||||
public abstract class NodeList<T extends Node> extends AbstractList<T> implements NodeIterable<T>, RandomAccess {
|
||||
|
||||
/**
|
||||
* This constant limits the maximum number of entries in a node list. The reason for the
|
||||
* limitations is the constraints of the code iterating over a node's inputs and successors. It
|
||||
* uses a bit data structure where only 16 bits are available for the current index into the
|
||||
* list. See the methods {@link NodeClass#getSuccessorIterable(Node)} and
|
||||
* {@link NodeClass#getInputIterable(Node)}.
|
||||
*/
|
||||
private static final int MAX_ENTRIES = 65536;
|
||||
|
||||
protected static final Node[] EMPTY_NODE_ARRAY = new Node[0];
|
||||
|
||||
protected final Node self;
|
||||
@ -50,6 +60,7 @@ public abstract class NodeList<T extends Node> extends AbstractList<T> implement
|
||||
|
||||
protected NodeList(Node self, int initialSize) {
|
||||
this.self = self;
|
||||
checkMaxSize(initialSize);
|
||||
this.size = initialSize;
|
||||
this.initialSize = initialSize;
|
||||
this.nodes = new Node[initialSize];
|
||||
@ -62,8 +73,9 @@ public abstract class NodeList<T extends Node> extends AbstractList<T> implement
|
||||
this.nodes = EMPTY_NODE_ARRAY;
|
||||
this.initialSize = 0;
|
||||
} else {
|
||||
checkMaxSize(elements.length);
|
||||
this.size = elements.length;
|
||||
this.initialSize = elements.length;
|
||||
this.initialSize = this.size;
|
||||
this.nodes = new Node[elements.length];
|
||||
for (int i = 0; i < elements.length; i++) {
|
||||
this.nodes[i] = elements[i];
|
||||
@ -79,8 +91,10 @@ public abstract class NodeList<T extends Node> extends AbstractList<T> implement
|
||||
this.nodes = EMPTY_NODE_ARRAY;
|
||||
this.initialSize = 0;
|
||||
} else {
|
||||
this.size = elements.size();
|
||||
this.initialSize = elements.size();
|
||||
int newSize = elements.size();
|
||||
checkMaxSize(newSize);
|
||||
this.size = newSize;
|
||||
this.initialSize = newSize;
|
||||
this.nodes = new Node[elements.size()];
|
||||
for (int i = 0; i < elements.size(); i++) {
|
||||
this.nodes[i] = elements.get(i);
|
||||
@ -89,6 +103,12 @@ public abstract class NodeList<T extends Node> extends AbstractList<T> implement
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkMaxSize(int value) {
|
||||
if (value > MAX_ENTRIES) {
|
||||
throw new PermanentBailoutException("Number of elements in a node list too high: %d", value);
|
||||
}
|
||||
}
|
||||
|
||||
protected NodeList(Node self, Collection<? extends NodeInterface> elements) {
|
||||
this.self = self;
|
||||
if (elements == null || elements.isEmpty()) {
|
||||
@ -96,8 +116,10 @@ public abstract class NodeList<T extends Node> extends AbstractList<T> implement
|
||||
this.nodes = EMPTY_NODE_ARRAY;
|
||||
this.initialSize = 0;
|
||||
} else {
|
||||
this.size = elements.size();
|
||||
this.initialSize = elements.size();
|
||||
int newSize = elements.size();
|
||||
checkMaxSize(newSize);
|
||||
this.size = newSize;
|
||||
this.initialSize = newSize;
|
||||
this.nodes = new Node[elements.size()];
|
||||
int i = 0;
|
||||
for (NodeInterface n : elements) {
|
||||
@ -109,7 +131,7 @@ public abstract class NodeList<T extends Node> extends AbstractList<T> implement
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes null values from the list.
|
||||
* Removes {@code null} values from the list.
|
||||
*/
|
||||
public void trim() {
|
||||
int newSize = 0;
|
||||
@ -150,10 +172,15 @@ public abstract class NodeList<T extends Node> extends AbstractList<T> implement
|
||||
modCount++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new node to the list. The total number of nodes in the list must not exceed
|
||||
* {@link #MAX_ENTRIES}, otherwise a {@link PermanentBailoutException} is thrown.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public boolean add(Node node) {
|
||||
assert node == null || !node.isDeleted() : node;
|
||||
checkMaxSize(size + 1);
|
||||
self.incModCount();
|
||||
incModCount();
|
||||
int length = nodes.length;
|
||||
@ -169,6 +196,9 @@ public abstract class NodeList<T extends Node> extends AbstractList<T> implement
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a node from the list given an {@code index}.
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public T get(int index) {
|
||||
@ -185,6 +215,9 @@ public abstract class NodeList<T extends Node> extends AbstractList<T> implement
|
||||
return get(size() - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the node of the list at the given {@code index} to a new value.
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public T set(int index, Node node) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -24,14 +24,15 @@
|
||||
|
||||
package org.graalvm.compiler.graph.spi;
|
||||
|
||||
import org.graalvm.compiler.core.common.spi.ConstantFieldProvider;
|
||||
import org.graalvm.compiler.core.common.spi.MetaAccessExtensionProvider;
|
||||
import org.graalvm.compiler.graph.Node;
|
||||
import org.graalvm.compiler.options.OptionValues;
|
||||
|
||||
import jdk.vm.ci.meta.Assumptions;
|
||||
import jdk.vm.ci.meta.ConstantReflectionProvider;
|
||||
import jdk.vm.ci.meta.MetaAccessProvider;
|
||||
|
||||
import org.graalvm.compiler.core.common.spi.ConstantFieldProvider;
|
||||
import org.graalvm.compiler.graph.Node;
|
||||
import org.graalvm.compiler.options.OptionValues;
|
||||
|
||||
public interface CanonicalizerTool {
|
||||
|
||||
Assumptions getAssumptions();
|
||||
@ -42,6 +43,8 @@ public interface CanonicalizerTool {
|
||||
|
||||
ConstantFieldProvider getConstantFieldProvider();
|
||||
|
||||
MetaAccessExtensionProvider getMetaAccessExtensionProvider();
|
||||
|
||||
boolean canonicalizeReads();
|
||||
|
||||
/**
|
||||
|
@ -54,6 +54,7 @@ import org.graalvm.compiler.hotspot.HotSpotDataBuilder;
|
||||
import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
|
||||
import org.graalvm.compiler.hotspot.HotSpotHostBackend;
|
||||
import org.graalvm.compiler.hotspot.HotSpotLIRGenerationResult;
|
||||
import org.graalvm.compiler.hotspot.HotSpotMarkId;
|
||||
import org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction;
|
||||
import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProvider;
|
||||
import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
|
||||
@ -81,7 +82,6 @@ import jdk.vm.ci.code.InstalledCode;
|
||||
import jdk.vm.ci.code.Register;
|
||||
import jdk.vm.ci.code.RegisterConfig;
|
||||
import jdk.vm.ci.code.StackSlot;
|
||||
import jdk.vm.ci.code.site.Mark;
|
||||
import jdk.vm.ci.hotspot.HotSpotCallingConventionType;
|
||||
import jdk.vm.ci.hotspot.HotSpotSentinelConstant;
|
||||
import jdk.vm.ci.hotspot.aarch64.AArch64HotSpotRegisterConfig;
|
||||
@ -152,9 +152,8 @@ public class AArch64HotSpotBackend extends HotSpotHostBackend implements LIRGene
|
||||
private boolean hasInvalidatePlaceholder(CompilationResult compilationResult) {
|
||||
byte[] targetCode = compilationResult.getTargetCode();
|
||||
int verifiedEntryOffset = 0;
|
||||
for (Mark mark : compilationResult.getMarks()) {
|
||||
Object markId = mark.id;
|
||||
if (markId instanceof Integer && (int) markId == config.MARKID_VERIFIED_ENTRY) {
|
||||
for (CompilationResult.CodeMark mark : compilationResult.getMarks()) {
|
||||
if (mark.id == HotSpotMarkId.VERIFIED_ENTRY || mark.id == HotSpotMarkId.OSR_ENTRY) {
|
||||
// The nmethod verified entry is located at some pc offset.
|
||||
verifiedEntryOffset = mark.pcOffset;
|
||||
break;
|
||||
@ -203,6 +202,9 @@ public class AArch64HotSpotBackend extends HotSpotHostBackend implements LIRGene
|
||||
}
|
||||
}
|
||||
}
|
||||
if (HotSpotMarkId.FRAME_COMPLETE.isAvailable()) {
|
||||
crb.recordMark(HotSpotMarkId.FRAME_COMPLETE);
|
||||
}
|
||||
if (ZapStackOnMethodEntry.getValue(crb.getOptions())) {
|
||||
try (ScratchRegister sc = masm.getScratchRegister()) {
|
||||
Register scratch = sc.getRegister();
|
||||
@ -312,7 +314,7 @@ public class AArch64HotSpotBackend extends HotSpotHostBackend implements LIRGene
|
||||
private void emitCodePrefix(CompilationResultBuilder crb, ResolvedJavaMethod installedCodeOwner, AArch64MacroAssembler masm, RegisterConfig regConfig, Label verifiedStub) {
|
||||
HotSpotProviders providers = getProviders();
|
||||
if (installedCodeOwner != null && !isStatic(installedCodeOwner.getModifiers())) {
|
||||
crb.recordMark(config.MARKID_UNVERIFIED_ENTRY);
|
||||
crb.recordMark(HotSpotMarkId.UNVERIFIED_ENTRY);
|
||||
CallingConvention cc = regConfig.getCallingConvention(HotSpotCallingConventionType.JavaCallee, null, new JavaType[]{providers.getMetaAccess().lookupJavaType(Object.class)}, this);
|
||||
// See definition of IC_Klass in c1_LIRAssembler_aarch64.cpp
|
||||
// equal to scratch(1) careful!
|
||||
@ -325,7 +327,7 @@ public class AArch64HotSpotBackend extends HotSpotHostBackend implements LIRGene
|
||||
Register klass = r10;
|
||||
if (config.useCompressedClassPointers) {
|
||||
masm.ldr(32, klass, klassAddress);
|
||||
AArch64HotSpotMove.decodeKlassPointer(crb, masm, klass, klass, config.getKlassEncoding(), config);
|
||||
AArch64HotSpotMove.decodeKlassPointer(crb, masm, klass, klass, config.getKlassEncoding());
|
||||
} else {
|
||||
masm.ldr(64, klass, klassAddress);
|
||||
}
|
||||
@ -338,9 +340,8 @@ public class AArch64HotSpotBackend extends HotSpotHostBackend implements LIRGene
|
||||
AArch64Call.directJmp(crb, masm, getForeignCalls().lookupForeignCall(IC_MISS_HANDLER));
|
||||
}
|
||||
masm.align(config.codeEntryAlignment);
|
||||
crb.recordMark(config.MARKID_OSR_ENTRY);
|
||||
masm.bind(verifiedStub);
|
||||
crb.recordMark(config.MARKID_VERIFIED_ENTRY);
|
||||
crb.recordMark(crb.compilationResult.getEntryBCI() != -1 ? HotSpotMarkId.OSR_ENTRY : HotSpotMarkId.VERIFIED_ENTRY);
|
||||
|
||||
if (GeneratePIC.getValue(crb.getOptions())) {
|
||||
// Check for method state
|
||||
@ -385,12 +386,12 @@ public class AArch64HotSpotBackend extends HotSpotHostBackend implements LIRGene
|
||||
HotSpotForeignCallsProvider foreignCalls = providers.getForeignCalls();
|
||||
try (ScratchRegister sc = masm.getScratchRegister()) {
|
||||
Register scratch = sc.getRegister();
|
||||
crb.recordMark(config.MARKID_EXCEPTION_HANDLER_ENTRY);
|
||||
crb.recordMark(HotSpotMarkId.EXCEPTION_HANDLER_ENTRY);
|
||||
ForeignCallLinkage linkage = foreignCalls.lookupForeignCall(EXCEPTION_HANDLER);
|
||||
Register helper = AArch64Call.isNearCall(linkage) ? null : scratch;
|
||||
AArch64Call.directCall(crb, masm, linkage, helper, null);
|
||||
}
|
||||
crb.recordMark(config.MARKID_DEOPT_HANDLER_ENTRY);
|
||||
crb.recordMark(HotSpotMarkId.DEOPT_HANDLER_ENTRY);
|
||||
ForeignCallLinkage linkage = foreignCalls.lookupForeignCall(DEOPT_BLOB_UNPACK);
|
||||
masm.adr(lr, 0); // Warning: the argument is an offset from the instruction!
|
||||
AArch64Call.directJmp(crb, masm, linkage);
|
||||
|
@ -36,6 +36,7 @@ import org.graalvm.compiler.bytecode.BytecodeProvider;
|
||||
import org.graalvm.compiler.core.aarch64.AArch64AddressLoweringByUse;
|
||||
import org.graalvm.compiler.core.aarch64.AArch64LIRKindTool;
|
||||
import org.graalvm.compiler.core.aarch64.AArch64SuitesCreator;
|
||||
import org.graalvm.compiler.core.common.spi.MetaAccessExtensionProvider;
|
||||
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
|
||||
import org.graalvm.compiler.hotspot.HotSpotBackend;
|
||||
import org.graalvm.compiler.hotspot.HotSpotBackendFactory;
|
||||
@ -44,11 +45,12 @@ import org.graalvm.compiler.hotspot.HotSpotReplacementsImpl;
|
||||
import org.graalvm.compiler.hotspot.meta.AddressLoweringHotSpotSuitesProvider;
|
||||
import org.graalvm.compiler.hotspot.meta.HotSpotConstantFieldProvider;
|
||||
import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProvider;
|
||||
import org.graalvm.compiler.hotspot.meta.HotSpotPlatformConfigurationProvider;
|
||||
import org.graalvm.compiler.hotspot.meta.HotSpotGraalConstantFieldProvider;
|
||||
import org.graalvm.compiler.hotspot.meta.HotSpotGraphBuilderPlugins;
|
||||
import org.graalvm.compiler.hotspot.meta.HotSpotHostForeignCallsProvider;
|
||||
import org.graalvm.compiler.hotspot.meta.HotSpotLoweringProvider;
|
||||
import org.graalvm.compiler.hotspot.meta.HotSpotMetaAccessExtensionProvider;
|
||||
import org.graalvm.compiler.hotspot.meta.HotSpotPlatformConfigurationProvider;
|
||||
import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
|
||||
import org.graalvm.compiler.hotspot.meta.HotSpotRegisters;
|
||||
import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider;
|
||||
@ -116,6 +118,7 @@ public class AArch64HotSpotBackendFactory extends HotSpotBackendFactory {
|
||||
HotSpotLoweringProvider lowerer;
|
||||
HotSpotStampProvider stampProvider;
|
||||
HotSpotPlatformConfigurationProvider platformConfigurationProvider;
|
||||
HotSpotMetaAccessExtensionProvider metaAccessExtensionProvider;
|
||||
HotSpotSnippetReflectionProvider snippetReflection;
|
||||
HotSpotReplacementsImpl replacements;
|
||||
HotSpotSuitesProvider suites;
|
||||
@ -141,11 +144,15 @@ public class AArch64HotSpotBackendFactory extends HotSpotBackendFactory {
|
||||
try (InitTimer rt = timer("create platform configuration provider")) {
|
||||
platformConfigurationProvider = createConfigInfoProvider(config, metaAccess);
|
||||
}
|
||||
try (InitTimer rt = timer("create MetaAccessExtensionProvider")) {
|
||||
metaAccessExtensionProvider = createMetaAccessExtensionProvider();
|
||||
}
|
||||
try (InitTimer rt = timer("create Lowerer provider")) {
|
||||
lowerer = createLowerer(graalRuntime, metaAccess, foreignCalls, registers, constantReflection, platformConfigurationProvider, target);
|
||||
lowerer = createLowerer(graalRuntime, metaAccess, foreignCalls, registers, constantReflection, platformConfigurationProvider, metaAccessExtensionProvider, target);
|
||||
}
|
||||
|
||||
Providers p = new Providers(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, null, stampProvider, platformConfigurationProvider);
|
||||
Providers p = new Providers(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, null, stampProvider, platformConfigurationProvider,
|
||||
metaAccessExtensionProvider);
|
||||
|
||||
try (InitTimer rt = timer("create SnippetReflection provider")) {
|
||||
snippetReflection = createSnippetReflection(graalRuntime, constantReflection, wordTypes);
|
||||
@ -165,7 +172,7 @@ public class AArch64HotSpotBackendFactory extends HotSpotBackendFactory {
|
||||
suites = createSuites(config, graalRuntime, compilerConfiguration, plugins, replacements);
|
||||
}
|
||||
providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, suites, registers,
|
||||
snippetReflection, wordTypes, plugins, platformConfigurationProvider);
|
||||
snippetReflection, wordTypes, plugins, platformConfigurationProvider, metaAccessExtensionProvider);
|
||||
replacements.setProviders(providers);
|
||||
replacements.maybeInitializeEncoder(options);
|
||||
}
|
||||
@ -197,7 +204,7 @@ public class AArch64HotSpotBackendFactory extends HotSpotBackendFactory {
|
||||
options,
|
||||
target);
|
||||
AArch64GraphBuilderPlugins.register(plugins, replacements, false, //
|
||||
/* registerMathPlugins */true, /* emitJDK9StringSubstitutions */true, config.useFMAIntrinsics);
|
||||
/* registerForeignCallMath */true, /* emitJDK9StringSubstitutions */true, config.useFMAIntrinsics);
|
||||
return plugins;
|
||||
}
|
||||
|
||||
@ -222,8 +229,10 @@ public class AArch64HotSpotBackendFactory extends HotSpotBackendFactory {
|
||||
}
|
||||
|
||||
protected HotSpotLoweringProvider createLowerer(HotSpotGraalRuntimeProvider runtime, HotSpotMetaAccessProvider metaAccess, HotSpotForeignCallsProvider foreignCalls,
|
||||
HotSpotRegistersProvider registers, HotSpotConstantReflectionProvider constantReflection, PlatformConfigurationProvider platformConfig, TargetDescription target) {
|
||||
return new AArch64HotSpotLoweringProvider(runtime, metaAccess, foreignCalls, registers, constantReflection, platformConfig, target);
|
||||
HotSpotRegistersProvider registers, HotSpotConstantReflectionProvider constantReflection, PlatformConfigurationProvider platformConfig,
|
||||
MetaAccessExtensionProvider metaAccessExtensionProvider,
|
||||
TargetDescription target) {
|
||||
return new AArch64HotSpotLoweringProvider(runtime, metaAccess, foreignCalls, registers, constantReflection, platformConfig, metaAccessExtensionProvider, target);
|
||||
}
|
||||
|
||||
protected static Value[] createNativeABICallerSaveRegisters(@SuppressWarnings("unused") GraalHotSpotVMConfig config, RegisterConfig regConfig) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2020, 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
|
||||
@ -28,6 +28,7 @@ import static jdk.vm.ci.hotspot.aarch64.AArch64HotSpotRegisterConfig.inlineCache
|
||||
|
||||
import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler;
|
||||
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
|
||||
import org.graalvm.compiler.hotspot.HotSpotMarkId;
|
||||
import org.graalvm.compiler.lir.LIRFrameState;
|
||||
import org.graalvm.compiler.lir.LIRInstructionClass;
|
||||
import org.graalvm.compiler.lir.Opcode;
|
||||
@ -58,14 +59,17 @@ final class AArch64HotSpotDirectStaticCallOp extends DirectCallOp {
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("try")
|
||||
public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) {
|
||||
// The mark for an invocation that uses an inline cache must be placed at the
|
||||
// instruction that loads the Klass from the inline cache.
|
||||
// For the first invocation this is set to a bitpattern that is guaranteed to never be a
|
||||
// valid object which causes the called function to call a handler that installs the
|
||||
// correct inline cache value here.
|
||||
crb.recordMark(invokeKind == InvokeKind.Static ? config.MARKID_INVOKESTATIC : config.MARKID_INVOKESPECIAL);
|
||||
masm.movNativeAddress(inlineCacheRegister, config.nonOopBits);
|
||||
super.emitCode(crb, masm);
|
||||
try (CompilationResultBuilder.CallContext callContext = crb.openCallContext(invokeKind.isDirect())) {
|
||||
// The mark for an invocation that uses an inline cache must be placed at the
|
||||
// instruction that loads the Klass from the inline cache.
|
||||
// For the first invocation this is set to a bitpattern that is guaranteed to never be a
|
||||
// valid object which causes the called function to call a handler that installs the
|
||||
// correct inline cache value here.
|
||||
crb.recordMark(invokeKind == InvokeKind.Static ? HotSpotMarkId.INVOKESTATIC : HotSpotMarkId.INVOKESPECIAL);
|
||||
masm.movNativeAddress(inlineCacheRegister, config.nonOopBits);
|
||||
super.emitCode(crb, masm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user