8193439: Update Graal
Reviewed-by: kvn
This commit is contained in:
parent
c11f132abe
commit
f287b874f2
@ -107,7 +107,6 @@ suite = {
|
||||
"subDir" : "share/classes",
|
||||
"dependencies" : ["JVMCI_SERVICES", "JVMCI_API", "org.graalvm.util"],
|
||||
"sourceDirs" : ["src"],
|
||||
"dependencies" : ["org.graalvm.util"],
|
||||
"checkstyle" : "org.graalvm.compiler.graph",
|
||||
"uses" : ["org.graalvm.compiler.options.OptionDescriptors"],
|
||||
"javaCompliance" : "1.8",
|
||||
@ -148,6 +147,7 @@ suite = {
|
||||
"dependencies" : [
|
||||
"JVMCI_API",
|
||||
"org.graalvm.compiler.serviceprovider",
|
||||
"org.graalvm.graphio",
|
||||
"org.graalvm.compiler.options"
|
||||
],
|
||||
"annotationProcessors" : ["GRAAL_OPTIONS_PROCESSOR"],
|
||||
@ -291,7 +291,6 @@ suite = {
|
||||
"subDir" : "share/classes",
|
||||
"sourceDirs" : ["src"],
|
||||
"dependencies" : [
|
||||
"org.graalvm.compiler.core.aarch64",
|
||||
"org.graalvm.compiler.hotspot",
|
||||
"org.graalvm.compiler.replacements.aarch64",
|
||||
],
|
||||
@ -435,6 +434,7 @@ suite = {
|
||||
"mx:JUNIT",
|
||||
"org.graalvm.compiler.api.test",
|
||||
"org.graalvm.compiler.graph",
|
||||
"org.graalvm.graphio",
|
||||
],
|
||||
"annotationProcessors" : ["GRAAL_NODEINFO_PROCESSOR"],
|
||||
"javaCompliance" : "1.8",
|
||||
@ -945,6 +945,7 @@ suite = {
|
||||
"dependencies" : [
|
||||
"org.graalvm.compiler.lir.jtt",
|
||||
"org.graalvm.compiler.lir.amd64",
|
||||
"org.graalvm.compiler.core.amd64",
|
||||
"JVMCI_HOTSPOT"
|
||||
],
|
||||
"checkstyle" : "org.graalvm.compiler.graph",
|
||||
@ -1019,7 +1020,6 @@ suite = {
|
||||
"subDir" : "share/classes",
|
||||
"sourceDirs" : ["src"],
|
||||
"dependencies" : [
|
||||
"org.graalvm.graphio",
|
||||
"org.graalvm.compiler.core",
|
||||
"org.graalvm.compiler.java",
|
||||
],
|
||||
|
@ -68,7 +68,7 @@ public class AArch64LIRKindTool implements LIRKindTool {
|
||||
|
||||
@Override
|
||||
public LIRKind getNarrowOopKind() {
|
||||
return LIRKind.reference(AArch64Kind.DWORD);
|
||||
return LIRKind.compressedReference(AArch64Kind.DWORD);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -33,8 +33,9 @@ import jdk.vm.ci.meta.ValueKind;
|
||||
|
||||
/**
|
||||
* Represents the type of values in the LIR. It is composed of a {@link PlatformKind} that gives the
|
||||
* low level representation of the value, and a {@link #referenceMask} that describes the location
|
||||
* of object references in the value, and optionally a {@link #derivedReferenceBase}.
|
||||
* low level representation of the value, a {@link #referenceMask} that describes the location of
|
||||
* object references in the value, a {@link #referenceCompressionMask} that indicates which of these
|
||||
* references are compressed references, and for derived references a {@link #derivedReferenceBase}.
|
||||
*
|
||||
* <h2>Constructing {@link LIRKind} instances</h2>
|
||||
*
|
||||
@ -52,7 +53,7 @@ import jdk.vm.ci.meta.ValueKind;
|
||||
* compare-and-swap. For convert operations, {@link LIRKind#combine} should be used.
|
||||
* <p>
|
||||
* If it is known that the result will be a reference (e.g. pointer arithmetic where the end result
|
||||
* is a valid oop), {@link LIRKind#reference} should be used.
|
||||
* is a valid oop), {@link #reference} or {@link LIRKind#compressedReference} should be used.
|
||||
* <p>
|
||||
* If it is known that the result will neither be a reference nor be derived from a reference,
|
||||
* {@link LIRKind#value} can be used. If the operation producing this value has inputs, this is very
|
||||
@ -64,19 +65,28 @@ import jdk.vm.ci.meta.ValueKind;
|
||||
*/
|
||||
public final class LIRKind extends ValueKind<LIRKind> {
|
||||
|
||||
/**
|
||||
* The location of object references in the value. If the value is a vector type, each bit
|
||||
* represents one component of the vector.
|
||||
*/
|
||||
private final int referenceMask;
|
||||
|
||||
/** Mask with 1-bits indicating which references in {@link #referenceMask} are compressed. */
|
||||
private final int referenceCompressionMask;
|
||||
|
||||
private AllocatableValue derivedReferenceBase;
|
||||
|
||||
private static final int UNKNOWN_REFERENCE = -1;
|
||||
|
||||
public static final LIRKind Illegal = unknownReference(ValueKind.Illegal.getPlatformKind());
|
||||
|
||||
private LIRKind(PlatformKind platformKind, int referenceMask, AllocatableValue derivedReferenceBase) {
|
||||
private LIRKind(PlatformKind platformKind, int referenceMask, int referenceCompressionMask, AllocatableValue derivedReferenceBase) {
|
||||
super(platformKind);
|
||||
this.referenceMask = referenceMask;
|
||||
this.referenceCompressionMask = referenceCompressionMask;
|
||||
this.derivedReferenceBase = derivedReferenceBase;
|
||||
|
||||
assert this.referenceCompressionMask == 0 || this.referenceMask == this.referenceCompressionMask : "mixing compressed and uncompressed references is untested";
|
||||
assert derivedReferenceBase == null || !derivedReferenceBase.getValueKind(LIRKind.class).isDerivedReference() : "derived reference can't have another derived reference as base";
|
||||
}
|
||||
|
||||
@ -86,15 +96,23 @@ public final class LIRKind extends ValueKind<LIRKind> {
|
||||
* reference. Otherwise, {@link #combine(Value...)} should be used instead.
|
||||
*/
|
||||
public static LIRKind value(PlatformKind platformKind) {
|
||||
return new LIRKind(platformKind, 0, null);
|
||||
return new LIRKind(platformKind, 0, 0, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link LIRKind} of type {@code platformKind} that contains a single tracked oop
|
||||
* reference.
|
||||
* Create a {@link LIRKind} of type {@code platformKind} that contains a single, tracked,
|
||||
* uncompressed oop reference.
|
||||
*/
|
||||
public static LIRKind reference(PlatformKind platformKind) {
|
||||
return derivedReference(platformKind, null);
|
||||
return derivedReference(platformKind, null, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link LIRKind} of type {@code platformKind} that contains a single, tracked,
|
||||
* compressed oop reference.
|
||||
*/
|
||||
public static LIRKind compressedReference(PlatformKind platformKind) {
|
||||
return derivedReference(platformKind, null, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -112,10 +130,12 @@ public final class LIRKind extends ValueKind<LIRKind> {
|
||||
/**
|
||||
* Create a {@link LIRKind} of type {@code platformKind} that contains a derived reference.
|
||||
*/
|
||||
public static LIRKind derivedReference(PlatformKind platformKind, AllocatableValue base) {
|
||||
public static LIRKind derivedReference(PlatformKind platformKind, AllocatableValue base, boolean compressed) {
|
||||
int length = platformKind.getVectorLength();
|
||||
assert 0 < length && length < 32 : "vector of " + length + " references not supported";
|
||||
return new LIRKind(platformKind, (1 << length) - 1, base);
|
||||
int referenceMask = (1 << length) - 1;
|
||||
int referenceCompressionMask = (compressed ? referenceMask : 0);
|
||||
return new LIRKind(platformKind, referenceMask, referenceCompressionMask, base);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -125,7 +145,7 @@ public final class LIRKind extends ValueKind<LIRKind> {
|
||||
* used instead to automatically propagate this information.
|
||||
*/
|
||||
public static LIRKind unknownReference(PlatformKind platformKind) {
|
||||
return new LIRKind(platformKind, UNKNOWN_REFERENCE, null);
|
||||
return new LIRKind(platformKind, UNKNOWN_REFERENCE, UNKNOWN_REFERENCE, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -139,9 +159,9 @@ public final class LIRKind extends ValueKind<LIRKind> {
|
||||
return makeUnknownReference();
|
||||
} else {
|
||||
if (isValue()) {
|
||||
return derivedReference(getPlatformKind(), base);
|
||||
return derivedReference(getPlatformKind(), base, false);
|
||||
} else {
|
||||
return new LIRKind(getPlatformKind(), referenceMask, base);
|
||||
return new LIRKind(getPlatformKind(), referenceMask, referenceCompressionMask, base);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -240,7 +260,7 @@ public final class LIRKind extends ValueKind<LIRKind> {
|
||||
return mergeKind;
|
||||
}
|
||||
/* {@code mergeKind} is a reference. */
|
||||
if (mergeKind.referenceMask != inputKind.referenceMask) {
|
||||
if (mergeKind.referenceMask != inputKind.referenceMask || mergeKind.referenceCompressionMask != inputKind.referenceCompressionMask) {
|
||||
/*
|
||||
* Reference masks do not match so the result can only be an unknown reference.
|
||||
*/
|
||||
@ -284,9 +304,11 @@ public final class LIRKind extends ValueKind<LIRKind> {
|
||||
} else {
|
||||
// reference type
|
||||
int newLength = Math.min(32, newPlatformKind.getVectorLength());
|
||||
int newReferenceMask = referenceMask & (0xFFFFFFFF >>> (32 - newLength));
|
||||
int lengthMask = 0xFFFFFFFF >>> (32 - newLength);
|
||||
int newReferenceMask = referenceMask & lengthMask;
|
||||
int newReferenceCompressionMask = referenceCompressionMask & lengthMask;
|
||||
assert newReferenceMask != UNKNOWN_REFERENCE;
|
||||
return new LIRKind(newPlatformKind, newReferenceMask, derivedReferenceBase);
|
||||
return new LIRKind(newPlatformKind, newReferenceMask, newReferenceCompressionMask, derivedReferenceBase);
|
||||
}
|
||||
}
|
||||
|
||||
@ -308,12 +330,14 @@ public final class LIRKind extends ValueKind<LIRKind> {
|
||||
|
||||
// repeat reference mask to fill new kind
|
||||
int newReferenceMask = 0;
|
||||
int newReferenceCompressionMask = 0;
|
||||
for (int i = 0; i < newLength; i += getPlatformKind().getVectorLength()) {
|
||||
newReferenceMask |= referenceMask << i;
|
||||
newReferenceCompressionMask |= referenceCompressionMask << i;
|
||||
}
|
||||
|
||||
assert newReferenceMask != UNKNOWN_REFERENCE;
|
||||
return new LIRKind(newPlatformKind, newReferenceMask, derivedReferenceBase);
|
||||
return new LIRKind(newPlatformKind, newReferenceMask, newReferenceCompressionMask, derivedReferenceBase);
|
||||
}
|
||||
}
|
||||
|
||||
@ -322,7 +346,7 @@ public final class LIRKind extends ValueKind<LIRKind> {
|
||||
* {@link LIRKind#unknownReference}.
|
||||
*/
|
||||
public LIRKind makeUnknownReference() {
|
||||
return new LIRKind(getPlatformKind(), UNKNOWN_REFERENCE, null);
|
||||
return new LIRKind(getPlatformKind(), UNKNOWN_REFERENCE, UNKNOWN_REFERENCE, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -384,6 +408,17 @@ public final class LIRKind extends ValueKind<LIRKind> {
|
||||
return !isUnknownReference() && (referenceMask & 1 << idx) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the {@code idx}th part of this value is a <b>compressed</b> reference.
|
||||
*
|
||||
* @param idx The index into the vector if this is a vector kind. Must be 0 if this is a scalar
|
||||
* kind.
|
||||
*/
|
||||
public boolean isCompressedReference(int idx) {
|
||||
assert 0 <= idx && idx < getPlatformKind().getVectorLength() : "invalid index " + idx + " in " + this;
|
||||
return !isUnknownReference() && (referenceCompressionMask & (1 << idx)) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether this kind is a value type that doesn't need to be tracked at safepoints.
|
||||
*/
|
||||
@ -432,6 +467,7 @@ public final class LIRKind extends ValueKind<LIRKind> {
|
||||
result = prime * result + ((getPlatformKind() == null) ? 0 : getPlatformKind().hashCode());
|
||||
result = prime * result + ((getDerivedReferenceBase() == null) ? 0 : getDerivedReferenceBase().hashCode());
|
||||
result = prime * result + referenceMask;
|
||||
result = prime * result + referenceCompressionMask;
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -445,7 +481,7 @@ public final class LIRKind extends ValueKind<LIRKind> {
|
||||
}
|
||||
|
||||
LIRKind other = (LIRKind) obj;
|
||||
if (getPlatformKind() != other.getPlatformKind() || referenceMask != other.referenceMask) {
|
||||
if (getPlatformKind() != other.getPlatformKind() || referenceMask != other.referenceMask || referenceCompressionMask != other.referenceCompressionMask) {
|
||||
return false;
|
||||
}
|
||||
if (isDerivedReference()) {
|
||||
|
@ -22,6 +22,7 @@
|
||||
*/
|
||||
package org.graalvm.compiler.core.common.util;
|
||||
|
||||
import org.graalvm.compiler.debug.Assertions;
|
||||
import org.graalvm.compiler.options.Option;
|
||||
import org.graalvm.compiler.options.OptionKey;
|
||||
import org.graalvm.compiler.options.OptionType;
|
||||
@ -34,7 +35,8 @@ public final class CompilationAlarm implements AutoCloseable {
|
||||
|
||||
public static class Options {
|
||||
// @formatter:off
|
||||
@Option(help = "Time limit in seconds before a compilation expires (0 to disable the limit).", type = OptionType.Debug)
|
||||
@Option(help = "Time limit in seconds before a compilation expires (0 to disable the limit). " +
|
||||
"The compilation alarm will be implicitly disabled if assertions are enabled.", type = OptionType.Debug)
|
||||
public static final OptionKey<Integer> CompilationExpirationPeriod = new OptionKey<>(300);
|
||||
// @formatter:on
|
||||
}
|
||||
@ -85,15 +87,16 @@ public final class CompilationAlarm implements AutoCloseable {
|
||||
|
||||
/**
|
||||
* Starts an alarm for setting a time limit on a compilation if there isn't already an active
|
||||
* alarm and {@link CompilationAlarm.Options#CompilationExpirationPeriod}{@code > 0}. The
|
||||
* returned value can be used in a try-with-resource statement to disable the alarm once the
|
||||
* compilation is finished.
|
||||
* alarm, if assertions are disabled and
|
||||
* {@link CompilationAlarm.Options#CompilationExpirationPeriod}{@code > 0}. The returned value
|
||||
* can be used in a try-with-resource statement to disable the alarm once the compilation is
|
||||
* finished.
|
||||
*
|
||||
* @return a {@link CompilationAlarm} if there was no current alarm for the calling thread
|
||||
* before this call otherwise {@code null}
|
||||
*/
|
||||
public static CompilationAlarm trackCompilationPeriod(OptionValues options) {
|
||||
int period = Options.CompilationExpirationPeriod.getValue(options);
|
||||
int period = Assertions.assertionsEnabled() ? 0 : Options.CompilationExpirationPeriod.getValue(options);
|
||||
if (period > 0) {
|
||||
CompilationAlarm current = currentAlarm.get();
|
||||
if (current == null) {
|
||||
@ -105,4 +108,5 @@ public final class CompilationAlarm implements AutoCloseable {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ public class SPARCLIRKindTool implements LIRKindTool {
|
||||
|
||||
@Override
|
||||
public LIRKind getNarrowOopKind() {
|
||||
return LIRKind.reference(SPARCKind.WORD);
|
||||
return LIRKind.compressedReference(SPARCKind.WORD);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,149 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 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.core.common.util.CompilationAlarm.Options.CompilationExpirationPeriod;
|
||||
|
||||
import org.graalvm.compiler.core.common.RetryableBailoutException;
|
||||
import org.graalvm.compiler.core.common.util.CompilationAlarm;
|
||||
import org.graalvm.compiler.debug.GraalError;
|
||||
import org.graalvm.compiler.nodes.StructuredGraph;
|
||||
import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
|
||||
import org.graalvm.compiler.options.OptionValues;
|
||||
import org.graalvm.compiler.phases.Phase;
|
||||
import org.junit.Test;
|
||||
|
||||
public class CooperativePhaseTest extends GraalCompilerTest {
|
||||
|
||||
public static void snippet() {
|
||||
// dummy snippet
|
||||
}
|
||||
|
||||
private static class CooperativePhase extends Phase {
|
||||
|
||||
@Override
|
||||
protected void run(StructuredGraph graph) {
|
||||
CompilationAlarm compilationAlarm = CompilationAlarm.current();
|
||||
while (true) {
|
||||
sleep(200);
|
||||
if (compilationAlarm.hasExpired()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class UnCooperativePhase extends Phase {
|
||||
|
||||
@Override
|
||||
protected void run(StructuredGraph graph) {
|
||||
CompilationAlarm compilationAlarm = CompilationAlarm.current();
|
||||
while (true) {
|
||||
sleep(200);
|
||||
if (compilationAlarm.hasExpired()) {
|
||||
throw new RetryableBailoutException("Expiring...");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class PartiallyCooperativePhase extends Phase {
|
||||
|
||||
@Override
|
||||
protected void run(StructuredGraph graph) {
|
||||
CompilationAlarm compilationAlarm = CompilationAlarm.current();
|
||||
for (int i = 0; i < 10; i++) {
|
||||
sleep(200);
|
||||
if (compilationAlarm.hasExpired()) {
|
||||
throw new RuntimeException("Phase must not exit in the timeout path");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class CooperativePhaseWithoutAlarm extends Phase {
|
||||
|
||||
@Override
|
||||
protected void run(StructuredGraph graph) {
|
||||
CompilationAlarm compilationAlarm = CompilationAlarm.current();
|
||||
if (compilationAlarm.hasExpired()) {
|
||||
throw new RuntimeException("Phase must not exit in the timeout path");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void sleep(long millis) {
|
||||
try {
|
||||
Thread.sleep(millis);
|
||||
} catch (InterruptedException e) {
|
||||
GraalError.shouldNotReachHere(e.getCause());
|
||||
}
|
||||
}
|
||||
|
||||
@Test(timeout = 60_000)
|
||||
@SuppressWarnings("try")
|
||||
public void test01() {
|
||||
initializeForTimeout();
|
||||
OptionValues initialOptions = getInitialOptions();
|
||||
OptionValues options = new OptionValues(initialOptions, CompilationExpirationPeriod, 1/* sec */);
|
||||
try (CompilationAlarm c1 = CompilationAlarm.trackCompilationPeriod(options)) {
|
||||
StructuredGraph g = parseEager("snippet", AllowAssumptions.NO, options);
|
||||
new CooperativePhase().apply(g);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = RetryableBailoutException.class, timeout = 60_000)
|
||||
@SuppressWarnings("try")
|
||||
public void test02() {
|
||||
initializeForTimeout();
|
||||
OptionValues initialOptions = getInitialOptions();
|
||||
OptionValues options = new OptionValues(initialOptions, CompilationExpirationPeriod, 1/* sec */);
|
||||
try (CompilationAlarm c1 = CompilationAlarm.trackCompilationPeriod(options)) {
|
||||
StructuredGraph g = parseEager("snippet", AllowAssumptions.NO, options);
|
||||
new UnCooperativePhase().apply(g);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(timeout = 60_000)
|
||||
@SuppressWarnings("try")
|
||||
public void test03() {
|
||||
initializeForTimeout();
|
||||
// 0 disables alarm utility
|
||||
OptionValues initialOptions = getInitialOptions();
|
||||
OptionValues options = new OptionValues(initialOptions, CompilationExpirationPeriod, 0);
|
||||
try (CompilationAlarm c1 = CompilationAlarm.trackCompilationPeriod(options)) {
|
||||
StructuredGraph g = parseEager("snippet", AllowAssumptions.NO, options);
|
||||
new PartiallyCooperativePhase().apply(g);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(timeout = 60_000)
|
||||
@SuppressWarnings("try")
|
||||
public void test04() {
|
||||
initializeForTimeout();
|
||||
StructuredGraph g = parseEager("snippet", AllowAssumptions.NO);
|
||||
new CooperativePhaseWithoutAlarm().apply(g);
|
||||
}
|
||||
}
|
@ -264,7 +264,7 @@ public class CountedLoopTest extends GraalCompilerTest {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean checkMidTierGraph(StructuredGraph graph) {
|
||||
protected boolean checkHighTierGraph(StructuredGraph graph) {
|
||||
LoopsData loops = new LoopsData(graph);
|
||||
loops.detectedCountedLoops();
|
||||
for (IVPropertyNode node : graph.getNodes().filter(IVPropertyNode.class)) {
|
||||
|
@ -54,8 +54,8 @@ public class Assertions {
|
||||
// @formatter:off
|
||||
public static class Options {
|
||||
|
||||
@Option(help = "Enable expensive assertions. (Require normal assertions enabled)", type = OptionType.Debug)
|
||||
public static final OptionKey<Boolean> DetailedAsserts = new OptionKey<>(true);
|
||||
@Option(help = "Enable expensive assertions if normal assertions (i.e. -ea or -esa) are enabled.", type = OptionType.Debug)
|
||||
public static final OptionKey<Boolean> DetailedAsserts = new OptionKey<>(false);
|
||||
|
||||
}
|
||||
// @formatter:on
|
||||
|
@ -472,6 +472,11 @@ public class Graph {
|
||||
}
|
||||
}
|
||||
|
||||
public <T extends Node> T addWithoutUniqueWithInputs(T node) {
|
||||
addInputs(node);
|
||||
return addHelper(node);
|
||||
}
|
||||
|
||||
private final class AddInputsFilter extends Node.EdgeVisitor {
|
||||
|
||||
@Override
|
||||
|
@ -30,6 +30,7 @@ import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.JUMP_ADDRES
|
||||
import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.PRESERVES_REGISTERS;
|
||||
import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF;
|
||||
import static org.graalvm.compiler.hotspot.replacements.CRC32Substitutions.UPDATE_BYTES_CRC32;
|
||||
import static org.graalvm.compiler.hotspot.replacements.CRC32CSubstitutions.UPDATE_BYTES_CRC32C;
|
||||
import static org.graalvm.word.LocationIdentity.any;
|
||||
|
||||
import org.graalvm.compiler.core.common.LIRKind;
|
||||
@ -79,6 +80,9 @@ public class AArch64HotSpotForeignCallsProvider extends HotSpotHostForeignCallsP
|
||||
if (config.useCRC32Intrinsics) {
|
||||
registerForeignCall(UPDATE_BYTES_CRC32, config.updateBytesCRC32Stub, NativeCall, PRESERVES_REGISTERS, LEAF, NOT_REEXECUTABLE, any());
|
||||
}
|
||||
if (config.useCRC32CIntrinsics) {
|
||||
registerForeignCall(UPDATE_BYTES_CRC32C, config.updateBytesCRC32C, NativeCall, PRESERVES_REGISTERS, LEAF, NOT_REEXECUTABLE, any());
|
||||
}
|
||||
|
||||
super.initialize(providers, options);
|
||||
}
|
||||
|
@ -30,8 +30,8 @@ import java.util.function.Function;
|
||||
|
||||
import org.graalvm.compiler.asm.Label;
|
||||
import org.graalvm.compiler.asm.aarch64.AArch64Address.AddressingMode;
|
||||
import org.graalvm.compiler.asm.aarch64.AArch64Assembler.PrefetchMode;
|
||||
import org.graalvm.compiler.asm.aarch64.AArch64Assembler.ConditionFlag;
|
||||
import org.graalvm.compiler.asm.aarch64.AArch64Assembler.PrefetchMode;
|
||||
import org.graalvm.compiler.core.aarch64.AArch64ArithmeticLIRGenerator;
|
||||
import org.graalvm.compiler.core.aarch64.AArch64LIRGenerator;
|
||||
import org.graalvm.compiler.core.aarch64.AArch64LIRKindTool;
|
||||
@ -202,7 +202,7 @@ public class AArch64HotSpotLIRGenerator extends AArch64LIRGenerator implements H
|
||||
assert inputKind.getPlatformKind() == AArch64Kind.QWORD;
|
||||
if (inputKind.isReference(0)) {
|
||||
// oop
|
||||
Variable result = newVariable(LIRKind.reference(AArch64Kind.DWORD));
|
||||
Variable result = newVariable(LIRKind.compressedReference(AArch64Kind.DWORD));
|
||||
append(new AArch64HotSpotMove.CompressPointer(result, asAllocatable(pointer), getProviders().getRegisters().getHeapBaseRegister().asValue(), encoding, nonNull));
|
||||
return result;
|
||||
} else {
|
||||
|
@ -33,6 +33,7 @@ import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEff
|
||||
import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF;
|
||||
import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF_NOFP;
|
||||
import static org.graalvm.compiler.hotspot.replacements.CRC32Substitutions.UPDATE_BYTES_CRC32;
|
||||
import static org.graalvm.compiler.hotspot.replacements.CRC32CSubstitutions.UPDATE_BYTES_CRC32C;
|
||||
import static org.graalvm.word.LocationIdentity.any;
|
||||
|
||||
import org.graalvm.compiler.core.common.LIRKind;
|
||||
@ -99,6 +100,9 @@ public class AMD64HotSpotForeignCallsProvider extends HotSpotHostForeignCallsPro
|
||||
// This stub does callee saving
|
||||
registerForeignCall(UPDATE_BYTES_CRC32, config.updateBytesCRC32Stub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, any());
|
||||
}
|
||||
if (config.useCRC32CIntrinsics) {
|
||||
registerForeignCall(UPDATE_BYTES_CRC32C, config.updateBytesCRC32C, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, any());
|
||||
}
|
||||
|
||||
super.initialize(providers, options);
|
||||
}
|
||||
|
@ -22,14 +22,15 @@
|
||||
*/
|
||||
package org.graalvm.compiler.hotspot.amd64;
|
||||
|
||||
import jdk.vm.ci.amd64.AMD64Kind;
|
||||
import org.graalvm.compiler.core.amd64.AMD64LIRKindTool;
|
||||
import org.graalvm.compiler.core.common.LIRKind;
|
||||
|
||||
import jdk.vm.ci.amd64.AMD64Kind;
|
||||
|
||||
public class AMD64HotSpotLIRKindTool extends AMD64LIRKindTool {
|
||||
@Override
|
||||
public LIRKind getNarrowOopKind() {
|
||||
return LIRKind.reference(AMD64Kind.DWORD);
|
||||
return LIRKind.compressedReference(AMD64Kind.DWORD);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -34,6 +34,7 @@ import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.JUMP_ADDRES
|
||||
import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.PRESERVES_REGISTERS;
|
||||
import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF_NOFP;
|
||||
import static org.graalvm.compiler.hotspot.replacements.CRC32Substitutions.UPDATE_BYTES_CRC32;
|
||||
import static org.graalvm.compiler.hotspot.replacements.CRC32CSubstitutions.UPDATE_BYTES_CRC32C;
|
||||
import static org.graalvm.word.LocationIdentity.any;
|
||||
|
||||
import org.graalvm.compiler.core.common.LIRKind;
|
||||
@ -87,6 +88,9 @@ public class SPARCHotSpotForeignCallsProvider extends HotSpotHostForeignCallsPro
|
||||
// This stub does callee saving
|
||||
registerForeignCall(UPDATE_BYTES_CRC32, config.updateBytesCRC32Stub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, any());
|
||||
}
|
||||
if (config.useCRC32CIntrinsics) {
|
||||
registerForeignCall(UPDATE_BYTES_CRC32C, config.updateBytesCRC32C, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, any());
|
||||
}
|
||||
|
||||
super.initialize(providers, options);
|
||||
}
|
||||
|
@ -307,7 +307,7 @@ public class SPARCHotSpotLIRGenerator extends SPARCLIRGenerator implements HotSp
|
||||
assert inputKind.getPlatformKind() == XWORD : inputKind;
|
||||
if (inputKind.isReference(0)) {
|
||||
// oop
|
||||
Variable result = newVariable(LIRKind.reference(WORD));
|
||||
Variable result = newVariable(LIRKind.compressedReference(WORD));
|
||||
append(new SPARCHotSpotMove.CompressPointer(result, asAllocatable(pointer), getProviders().getRegisters().getHeapBaseRegister().asValue(), encoding, nonNull));
|
||||
return result;
|
||||
} else {
|
||||
|
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package org.graalvm.compiler.hotspot.test;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.zip.Checksum;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
|
||||
import org.graalvm.compiler.test.GraalTest;
|
||||
import org.graalvm.compiler.core.test.GraalCompilerTest;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assume.assumeFalse;
|
||||
|
||||
/**
|
||||
* Tests compiled calls to {@link java.util.zip.CRC32C}.
|
||||
*/
|
||||
@SuppressWarnings("javadoc")
|
||||
public class CRC32CSubstitutionsTest extends GraalCompilerTest {
|
||||
|
||||
public static long updateBytes(byte[] input, int offset, int end) throws Throwable {
|
||||
Class<?> crcClass = Class.forName("java.util.zip.CRC32C");
|
||||
MethodHandle newMH = MethodHandles.publicLookup().findConstructor(crcClass, MethodType.methodType(void.class));
|
||||
Checksum crc = (Checksum) newMH.invoke();
|
||||
crc.update(input, offset, end);
|
||||
return crc.getValue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test1() throws Throwable {
|
||||
assumeFalse(GraalTest.Java8OrEarlier);
|
||||
String classfileName = CRC32CSubstitutionsTest.class.getSimpleName().replace('.', '/') + ".class";
|
||||
InputStream s = CRC32CSubstitutionsTest.class.getResourceAsStream(classfileName);
|
||||
byte[] buf = new byte[s.available()];
|
||||
new DataInputStream(s).readFully(buf);
|
||||
int end = buf.length;
|
||||
for (int offset = 0; offset < buf.length; offset++) {
|
||||
test("updateBytes", buf, offset, end);
|
||||
}
|
||||
}
|
||||
|
||||
public static long updateByteBuffer(ByteBuffer buffer) throws Throwable {
|
||||
Class<?> crcClass = Class.forName("java.util.zip.CRC32C");
|
||||
MethodHandle newMH = MethodHandles.publicLookup().findConstructor(crcClass, MethodType.methodType(void.class));
|
||||
MethodHandle updateMH = MethodHandles.publicLookup().findVirtual(crcClass, "update", MethodType.methodType(void.class, ByteBuffer.class));
|
||||
Checksum crc = (Checksum) newMH.invoke();
|
||||
buffer.rewind();
|
||||
updateMH.invokeExact(crc, buffer); // Checksum.update(ByteBuffer) is also available since 9
|
||||
return crc.getValue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test2() throws Throwable {
|
||||
assumeFalse(GraalTest.Java8OrEarlier);
|
||||
String classfileName = CRC32CSubstitutionsTest.class.getSimpleName().replace('.', '/') + ".class";
|
||||
InputStream s = CRC32CSubstitutionsTest.class.getResourceAsStream(classfileName);
|
||||
byte[] buf = new byte[s.available()];
|
||||
new DataInputStream(s).readFully(buf);
|
||||
|
||||
ByteBuffer directBuf = ByteBuffer.allocateDirect(buf.length);
|
||||
directBuf.put(buf);
|
||||
ByteBuffer heapBuf = ByteBuffer.wrap(buf);
|
||||
|
||||
test("updateByteBuffer", directBuf);
|
||||
test("updateByteBuffer", heapBuf);
|
||||
}
|
||||
|
||||
}
|
@ -466,6 +466,13 @@ public class CheckGraalIntrinsics extends GraalTest {
|
||||
}
|
||||
}
|
||||
|
||||
// CRC32C intrinsics
|
||||
if (!config.useCRC32CIntrinsics) {
|
||||
add(IGNORE,
|
||||
"java/util/zip/CRC32C.updateBytes(I[BII)I",
|
||||
"java/util/zip/CRC32C.updateDirectByteBuffer(IJII)I");
|
||||
}
|
||||
|
||||
// AES intrinsics
|
||||
if (!config.useAESIntrinsics) {
|
||||
if (isJDK9OrHigher()) {
|
||||
|
@ -33,9 +33,9 @@ import org.graalvm.compiler.code.CompilationResult;
|
||||
import org.graalvm.compiler.core.common.LIRKind;
|
||||
import org.graalvm.compiler.core.common.type.StampFactory;
|
||||
import org.graalvm.compiler.core.test.GraalCompilerTest;
|
||||
import org.graalvm.compiler.debug.DebugHandlersFactory;
|
||||
import org.graalvm.compiler.debug.DebugContext;
|
||||
import org.graalvm.compiler.debug.DebugContext.Scope;
|
||||
import org.graalvm.compiler.debug.DebugHandlersFactory;
|
||||
import org.graalvm.compiler.graph.NodeClass;
|
||||
import org.graalvm.compiler.hotspot.HotSpotCompiledCodeBuilder;
|
||||
import org.graalvm.compiler.lir.FullInfopointOp;
|
||||
@ -150,7 +150,7 @@ public class JVMCIInfopointErrorTest extends GraalCompilerTest {
|
||||
codeCache.addCode(method, compiledCode, null, null);
|
||||
}
|
||||
|
||||
@Test(expected = JVMCIError.class)
|
||||
@Test(expected = Error.class)
|
||||
public void testInvalidShortOop() {
|
||||
test((tool, state, safepoint) -> {
|
||||
PlatformKind kind = tool.target().arch.getPlatformKind(JavaKind.Short);
|
||||
@ -163,14 +163,14 @@ public class JVMCIInfopointErrorTest extends GraalCompilerTest {
|
||||
});
|
||||
}
|
||||
|
||||
@Test(expected = JVMCIError.class)
|
||||
@Test(expected = Error.class)
|
||||
public void testInvalidShortDerivedOop() {
|
||||
test((tool, state, safepoint) -> {
|
||||
Variable baseOop = tool.newVariable(LIRKind.fromJavaKind(tool.target().arch, JavaKind.Object));
|
||||
tool.append(new ValueDef(baseOop));
|
||||
|
||||
PlatformKind kind = tool.target().arch.getPlatformKind(JavaKind.Short);
|
||||
LIRKind lirKind = LIRKind.derivedReference(kind, baseOop);
|
||||
LIRKind lirKind = LIRKind.derivedReference(kind, baseOop, false);
|
||||
|
||||
Variable var = tool.newVariable(lirKind);
|
||||
tool.append(new ValueDef(var));
|
||||
|
@ -165,6 +165,7 @@ public class GraalHotSpotVMConfig extends HotSpotVMConfigAccess {
|
||||
public final boolean usePopCountInstruction = getFlag("UsePopCountInstruction", Boolean.class);
|
||||
public final boolean useAESIntrinsics = getFlag("UseAESIntrinsics", Boolean.class);
|
||||
public final boolean useCRC32Intrinsics = getFlag("UseCRC32Intrinsics", Boolean.class);
|
||||
public final boolean useCRC32CIntrinsics = isJDK8 ? false : getFlag("UseCRC32CIntrinsics", Boolean.class);
|
||||
public final boolean threadLocalHandshakes = getFlag("ThreadLocalHandshakes", Boolean.class, false);
|
||||
|
||||
private final boolean useMultiplyToLenIntrinsic = getFlag("UseMultiplyToLenIntrinsic", Boolean.class);
|
||||
|
@ -45,6 +45,7 @@ import jdk.vm.ci.code.CallingConvention;
|
||||
import jdk.vm.ci.common.InitTimer;
|
||||
import jdk.vm.ci.hotspot.HotSpotCallingConventionType;
|
||||
import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
|
||||
import jdk.vm.ci.meta.JavaKind;
|
||||
import jdk.vm.ci.meta.JavaType;
|
||||
import jdk.vm.ci.runtime.JVMCICompiler;
|
||||
|
||||
@ -142,7 +143,8 @@ public abstract class HotSpotHostBackend extends HotSpotBackend {
|
||||
|
||||
@Override
|
||||
public ReferenceMapBuilder newReferenceMapBuilder(int totalFrameSize) {
|
||||
return new HotSpotReferenceMapBuilder(totalFrameSize, config.maxOopMapStackOffset);
|
||||
int uncompressedReferenceSize = getTarget().arch.getPlatformKind(JavaKind.Object).getSizeInBytes();
|
||||
return new HotSpotReferenceMapBuilder(totalFrameSize, config.maxOopMapStackOffset, uncompressedReferenceSize);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -22,15 +22,15 @@
|
||||
*/
|
||||
package org.graalvm.compiler.hotspot;
|
||||
|
||||
import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant;
|
||||
import static jdk.vm.ci.code.ValueUtil.asRegister;
|
||||
import static jdk.vm.ci.code.ValueUtil.asStackSlot;
|
||||
import static jdk.vm.ci.code.ValueUtil.isRegister;
|
||||
import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.graalvm.compiler.core.common.PermanentBailoutException;
|
||||
import org.graalvm.compiler.core.common.LIRKind;
|
||||
import org.graalvm.compiler.core.common.PermanentBailoutException;
|
||||
import org.graalvm.compiler.debug.GraalError;
|
||||
import org.graalvm.compiler.lir.LIRFrameState;
|
||||
import org.graalvm.compiler.lir.Variable;
|
||||
@ -52,8 +52,10 @@ public final class HotSpotReferenceMapBuilder extends ReferenceMapBuilder {
|
||||
|
||||
private final int totalFrameSize;
|
||||
private final int maxOopMapStackOffset;
|
||||
private final int uncompressedReferenceSize;
|
||||
|
||||
public HotSpotReferenceMapBuilder(int totalFrameSize, int maxOopMapStackOffset) {
|
||||
public HotSpotReferenceMapBuilder(int totalFrameSize, int maxOopMapStackOffset, int uncompressedReferenceSize) {
|
||||
this.uncompressedReferenceSize = uncompressedReferenceSize;
|
||||
this.objectValues = new ArrayList<>();
|
||||
this.objectCount = 0;
|
||||
this.maxOopMapStackOffset = maxOopMapStackOffset;
|
||||
@ -116,6 +118,7 @@ public final class HotSpotReferenceMapBuilder extends ReferenceMapBuilder {
|
||||
|
||||
for (int i = 0; i < kind.getPlatformKind().getVectorLength(); i++) {
|
||||
if (kind.isReference(i)) {
|
||||
assert kind.isCompressedReference(i) ? (bytes < uncompressedReferenceSize) : (bytes == uncompressedReferenceSize);
|
||||
objects[idx] = toLocation(obj, i * bytes);
|
||||
derivedBase[idx] = base;
|
||||
sizeInBytes[idx] = bytes;
|
||||
|
@ -46,6 +46,7 @@ import org.graalvm.compiler.hotspot.nodes.CurrentJavaThreadNode;
|
||||
import org.graalvm.compiler.hotspot.replacements.AESCryptSubstitutions;
|
||||
import org.graalvm.compiler.hotspot.replacements.BigIntegerSubstitutions;
|
||||
import org.graalvm.compiler.hotspot.replacements.CRC32Substitutions;
|
||||
import org.graalvm.compiler.hotspot.replacements.CRC32CSubstitutions;
|
||||
import org.graalvm.compiler.hotspot.replacements.CallSiteTargetNode;
|
||||
import org.graalvm.compiler.hotspot.replacements.CipherBlockChainingSubstitutions;
|
||||
import org.graalvm.compiler.hotspot.replacements.ClassGetHubNode;
|
||||
@ -165,6 +166,7 @@ public class HotSpotGraphBuilderPlugins {
|
||||
registerConstantPoolPlugins(invocationPlugins, wordTypes, config, replacementBytecodeProvider);
|
||||
registerAESPlugins(invocationPlugins, config, replacementBytecodeProvider);
|
||||
registerCRC32Plugins(invocationPlugins, config, replacementBytecodeProvider);
|
||||
registerCRC32CPlugins(invocationPlugins, config, replacementBytecodeProvider);
|
||||
registerBigIntegerPlugins(invocationPlugins, config, replacementBytecodeProvider);
|
||||
registerSHAPlugins(invocationPlugins, config, replacementBytecodeProvider);
|
||||
registerUnsafePlugins(invocationPlugins, replacementBytecodeProvider);
|
||||
@ -530,4 +532,12 @@ public class HotSpotGraphBuilderPlugins {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void registerCRC32CPlugins(InvocationPlugins plugins, GraalHotSpotVMConfig config, BytecodeProvider bytecodeProvider) {
|
||||
if (config.useCRC32CIntrinsics) {
|
||||
Registration r = new Registration(plugins, "java.util.zip.CRC32C", bytecodeProvider);
|
||||
r.registerMethodSubstitution(CRC32CSubstitutions.class, "updateBytes", int.class, byte[].class, int.class, int.class);
|
||||
r.registerMethodSubstitution(CRC32CSubstitutions.class, "updateDirectByteBuffer", int.class, long.class, int.class, int.class);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package org.graalvm.compiler.hotspot.replacements;
|
||||
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.arrayBaseOffset;
|
||||
|
||||
import org.graalvm.compiler.api.replacements.ClassSubstitution;
|
||||
import org.graalvm.compiler.api.replacements.MethodSubstitution;
|
||||
import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
|
||||
import org.graalvm.compiler.graph.Node.ConstantNodeParameter;
|
||||
import org.graalvm.compiler.graph.Node.NodeIntrinsic;
|
||||
import org.graalvm.compiler.hotspot.nodes.ComputeObjectAddressNode;
|
||||
import org.graalvm.compiler.nodes.extended.ForeignCallNode;
|
||||
import org.graalvm.compiler.word.Word;
|
||||
import org.graalvm.word.WordBase;
|
||||
import org.graalvm.word.WordFactory;
|
||||
|
||||
import jdk.vm.ci.meta.JavaKind;
|
||||
|
||||
// JaCoCo Exclude
|
||||
|
||||
/**
|
||||
* Substitutions for java.util.zip.CRC32C.
|
||||
*/
|
||||
@ClassSubstitution(className = "java.util.zip.CRC32C", optional = true)
|
||||
public class CRC32CSubstitutions {
|
||||
|
||||
@MethodSubstitution
|
||||
static int updateBytes(int crc, byte[] b, int off, int end) {
|
||||
Word bufAddr = WordFactory.unsigned(ComputeObjectAddressNode.get(b, arrayBaseOffset(JavaKind.Byte) + off));
|
||||
return updateBytesCRC32(UPDATE_BYTES_CRC32C, crc, bufAddr, end - off);
|
||||
}
|
||||
|
||||
@MethodSubstitution
|
||||
static int updateDirectByteBuffer(int crc, long addr, int off, int end) {
|
||||
WordBase bufAddr = WordFactory.unsigned(addr).add(off);
|
||||
return updateBytesCRC32(UPDATE_BYTES_CRC32C, crc, bufAddr, end - off);
|
||||
}
|
||||
|
||||
public static final ForeignCallDescriptor UPDATE_BYTES_CRC32C = new ForeignCallDescriptor("updateBytesCRC32C", int.class, int.class, WordBase.class, int.class);
|
||||
|
||||
@NodeIntrinsic(ForeignCallNode.class)
|
||||
public static native int updateBytesCRC32(@ConstantNodeParameter ForeignCallDescriptor descriptor, int crc, WordBase buf, int length);
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package org.graalvm.compiler.jtt.bytecode;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.graalvm.compiler.jtt.JTTTest;
|
||||
|
||||
/*
|
||||
*/
|
||||
public class BC_idiv_overflow extends JTTTest {
|
||||
|
||||
public static int test(int a, int b) {
|
||||
return a / (b | 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void run0() throws Throwable {
|
||||
runTest("test", Integer.MIN_VALUE, -1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void run1() throws Throwable {
|
||||
runTest("test", Integer.MIN_VALUE, 1);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package org.graalvm.compiler.jtt.bytecode;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.graalvm.compiler.jtt.JTTTest;
|
||||
|
||||
/*
|
||||
*/
|
||||
public class BC_ldiv_overflow extends JTTTest {
|
||||
|
||||
public static long test(long a, long b) {
|
||||
return a / (b | 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void run0() throws Throwable {
|
||||
runTest("test", Long.MIN_VALUE, -1L);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void run1() throws Throwable {
|
||||
runTest("test", Long.MIN_VALUE, 1L);
|
||||
}
|
||||
|
||||
}
|
@ -30,8 +30,6 @@ import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import jdk.vm.ci.meta.MetaAccessProvider;
|
||||
import jdk.vm.ci.meta.ResolvedJavaType;
|
||||
import org.graalvm.compiler.core.common.calc.Condition;
|
||||
import org.graalvm.compiler.core.common.type.IntegerStamp;
|
||||
import org.graalvm.compiler.core.common.type.Stamp;
|
||||
@ -67,7 +65,9 @@ import org.graalvm.util.Equivalence;
|
||||
import jdk.vm.ci.meta.Constant;
|
||||
import jdk.vm.ci.meta.JavaConstant;
|
||||
import jdk.vm.ci.meta.JavaKind;
|
||||
import jdk.vm.ci.meta.MetaAccessProvider;
|
||||
import jdk.vm.ci.meta.PrimitiveConstant;
|
||||
import jdk.vm.ci.meta.ResolvedJavaType;
|
||||
|
||||
/**
|
||||
* The {@code IfNode} represents a branch that can go one of two directions depending on the outcome
|
||||
@ -416,6 +416,7 @@ public final class IfNode extends ControlSplitNode implements Simplifiable, LIRL
|
||||
if (result.graph() == null) {
|
||||
result = graph().addOrUniqueWithInputs(result);
|
||||
}
|
||||
result = proxyReplacement(result);
|
||||
/*
|
||||
* This optimization can be performed even if multiple values merge at this phi
|
||||
* since the two inputs get simplified into one.
|
||||
@ -698,6 +699,7 @@ public final class IfNode extends ControlSplitNode implements Simplifiable, LIRL
|
||||
ValueNode falseValue = singlePhi.valueAt(falseEnd);
|
||||
ValueNode conditional = canonicalizeConditionalCascade(tool, trueValue, falseValue);
|
||||
if (conditional != null) {
|
||||
conditional = proxyReplacement(conditional);
|
||||
singlePhi.setValueAt(trueEnd, conditional);
|
||||
removeThroughFalseBranch(tool, merge);
|
||||
return true;
|
||||
@ -729,6 +731,36 @@ public final class IfNode extends ControlSplitNode implements Simplifiable, LIRL
|
||||
return false;
|
||||
}
|
||||
|
||||
private ValueNode proxyReplacement(ValueNode replacement) {
|
||||
/*
|
||||
* Special case: Every empty diamond we collapse to a conditional node can potentially
|
||||
* contain loop exit nodes on both branches. See the graph below: The two loop exits
|
||||
* (instanceof begin node) exit the same loop. The resulting phi is defined outside the
|
||||
* loop, but the resulting conditional node will be inside the loop, so we need to proxy the
|
||||
* resulting conditional node. Callers of this method ensure that true and false successor
|
||||
* have no usages, therefore a and b in the graph below can never be proxies themselves.
|
||||
*/
|
||||
// @formatter:off
|
||||
// +--+
|
||||
// |If|
|
||||
// +--+ +-----+ +-----+
|
||||
// +----+ +----+ | a | | b |
|
||||
// |Lex | |Lex | +----^+ +^----+
|
||||
// +----+ +----+ | |
|
||||
// +-------+ +---+
|
||||
// | Merge +---------+Phi|
|
||||
// +-------+ +---+
|
||||
// @formatter:on
|
||||
if (this.graph().hasValueProxies()) {
|
||||
if (trueSuccessor instanceof LoopExitNode && falseSuccessor instanceof LoopExitNode) {
|
||||
assert ((LoopExitNode) trueSuccessor).loopBegin() == ((LoopExitNode) falseSuccessor).loopBegin();
|
||||
assert trueSuccessor.usages().isEmpty() && falseSuccessor.usages().isEmpty();
|
||||
return this.graph().addOrUnique(new ValueProxyNode(replacement, (LoopExitNode) trueSuccessor));
|
||||
}
|
||||
}
|
||||
return replacement;
|
||||
}
|
||||
|
||||
protected void removeThroughFalseBranch(SimplifierTool tool, AbstractMergeNode merge) {
|
||||
AbstractBeginNode trueBegin = trueSuccessor();
|
||||
LogicNode conditionNode = condition();
|
||||
|
@ -60,7 +60,8 @@ public abstract class IntegerDivRemNode extends FixedBinaryNode implements Lower
|
||||
|
||||
// Assigning canDeopt during constructor, because it must never change during lifetime of
|
||||
// the node.
|
||||
this.canDeopt = ((IntegerStamp) getY().stamp(NodeView.DEFAULT)).contains(0);
|
||||
IntegerStamp yStamp = (IntegerStamp) getY().stamp(NodeView.DEFAULT);
|
||||
this.canDeopt = yStamp.contains(0) || yStamp.contains(-1);
|
||||
}
|
||||
|
||||
public final Op getOp() {
|
||||
|
@ -121,7 +121,7 @@ public class ProfileCompiledMethodsPhase extends Phase {
|
||||
|
||||
private static void addSectionCounters(FixedWithNextNode start, Collection<Block> sectionBlocks, Collection<Loop<Block>> childLoops, ScheduleResult schedule, ControlFlowGraph cfg) {
|
||||
HashSet<Block> blocks = new HashSet<>(sectionBlocks);
|
||||
for (Loop<?> loop : childLoops) {
|
||||
for (Loop<Block> loop : childLoops) {
|
||||
blocks.removeAll(loop.getBlocks());
|
||||
}
|
||||
double weight = getSectionWeight(schedule, blocks) / cfg.blockFor(start).probability();
|
||||
|
@ -194,15 +194,26 @@ interface GraphPrinter extends Closeable, JavaConstantFormatter {
|
||||
|
||||
static String constantToString(Object value) {
|
||||
Class<?> c = value.getClass();
|
||||
String suffix = "";
|
||||
if (c.isArray()) {
|
||||
return constantArrayToString(value);
|
||||
} else if (value instanceof Enum) {
|
||||
return ((Enum<?>) value).name();
|
||||
} else if (isToStringTrusted(c)) {
|
||||
try {
|
||||
return value.toString();
|
||||
} catch (Throwable t) {
|
||||
suffix = "[toString error: " + t.getClass().getName() + "]";
|
||||
if (isToStringTrusted(t.getClass())) {
|
||||
try {
|
||||
suffix = "[toString error: " + t + "]";
|
||||
} catch (Throwable t2) {
|
||||
// No point in going further
|
||||
}
|
||||
return MetaUtil.getSimpleName(c, true) + "@" + Integer.toHexString(System.identityHashCode(value));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
return MetaUtil.getSimpleName(c, true) + "@" + Integer.toHexString(System.identityHashCode(value)) + suffix;
|
||||
}
|
||||
|
||||
static String constantArrayToString(Object array) {
|
||||
|
@ -141,6 +141,7 @@ public class StandardGraphBuilderPlugins {
|
||||
registerJMHBlackholePlugins(plugins, bytecodeProvider);
|
||||
registerJFRThrowablePlugins(plugins, bytecodeProvider);
|
||||
registerMethodHandleImplPlugins(plugins, snippetReflection, bytecodeProvider);
|
||||
registerJcovCollectPlugins(plugins, bytecodeProvider);
|
||||
}
|
||||
|
||||
private static final Field STRING_VALUE_FIELD;
|
||||
@ -910,4 +911,21 @@ public class StandardGraphBuilderPlugins {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a plugin to ignore {@code com.sun.tdk.jcov.runtime.Collect.hit} within an
|
||||
* intrinsic.
|
||||
*/
|
||||
private static void registerJcovCollectPlugins(InvocationPlugins plugins, BytecodeProvider bytecodeProvider) {
|
||||
Registration r = new Registration(plugins, "com.sun.tdk.jcov.runtime.Collect", bytecodeProvider);
|
||||
r.register1("hit", int.class, new InvocationPlugin() {
|
||||
@Override
|
||||
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode object) {
|
||||
if (b.parsingIntrinsic()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 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,8 +46,8 @@ public class Classfile {
|
||||
private final ResolvedJavaType type;
|
||||
private final List<ClassfileBytecode> codeAttributes;
|
||||
|
||||
private static final int MAJOR_VERSION_JAVA_MIN = 51;
|
||||
private static final int MAJOR_VERSION_JAVA_MAX = 54;
|
||||
private static final int MAJOR_VERSION_JAVA7 = 51;
|
||||
private static final int MAJOR_VERSION_JAVA10 = 54;
|
||||
private static final int MAGIC = 0xCAFEBABE;
|
||||
|
||||
/**
|
||||
@ -65,7 +65,7 @@ public class Classfile {
|
||||
|
||||
int minor = stream.readUnsignedShort();
|
||||
int major = stream.readUnsignedShort();
|
||||
if (major < MAJOR_VERSION_JAVA_MIN || major > MAJOR_VERSION_JAVA_MAX) {
|
||||
if (major < MAJOR_VERSION_JAVA7 || major > MAJOR_VERSION_JAVA10) {
|
||||
throw new UnsupportedClassVersionError("Unsupported class file version: " + major + "." + minor);
|
||||
}
|
||||
|
||||
|
@ -34,7 +34,6 @@ import org.graalvm.compiler.nodes.IfNode;
|
||||
import org.graalvm.compiler.nodes.NodeView;
|
||||
import org.graalvm.compiler.nodes.PhiNode;
|
||||
import org.graalvm.compiler.nodes.PiNode;
|
||||
import org.graalvm.compiler.nodes.ProxyNode;
|
||||
import org.graalvm.compiler.nodes.StructuredGraph;
|
||||
import org.graalvm.compiler.nodes.ValueNode;
|
||||
import org.graalvm.compiler.nodes.debug.DynamicCounterNode;
|
||||
@ -116,14 +115,7 @@ public final class GraphEffectList extends EffectList {
|
||||
*/
|
||||
public void addFloatingNode(ValueNode node, @SuppressWarnings("unused") String cause) {
|
||||
add("add floating node", graph -> {
|
||||
if (node instanceof ProxyNode) {
|
||||
ProxyNode proxyNode = (ProxyNode) node;
|
||||
ValueNode value = proxyNode.value();
|
||||
if (!value.isAlive()) {
|
||||
graph.addWithoutUnique(value);
|
||||
}
|
||||
}
|
||||
graph.addWithoutUnique(node);
|
||||
graph.addWithoutUniqueWithInputs(node);
|
||||
});
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user