8226771: Update Graal
Reviewed-by: kvn
This commit is contained in:
parent
a8af569fa0
commit
bc1ccab62c
src
jdk.internal.vm.compiler.management/share/classes/org.graalvm.compiler.hotspot.management/src/org/graalvm/compiler/hotspot/management
jdk.internal.vm.compiler/share/classes
jdk.internal.vm.compiler.libgraal/src/jdk/internal/vm/compiler/libgraal
org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test
org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test
org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64
AArch64LoweringProviderMixin.javaAArch64ReadNode.javaAArch64ReadReplacementPhase.javaAArch64SuitesCreator.java
org.graalvm.compiler.core.amd64.test/src/org/graalvm/compiler/core/amd64/test
org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64
AMD64ArithmeticLIRGenerator.javaAMD64LIRGenerator.javaAMD64LoweringProviderMixin.javaAMD64MoveFactory.java
org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common
org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc
org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test
ConditionalEliminationPiTest.javaConditionalNodeTest.javaDumpPathTest.javaFindUniqueConcreteMethodBugTest.javaGraalCompilerTest.javaSwitchFoldingTest.java
backend
org.graalvm.compiler.core/src/org/graalvm/compiler/core
org.graalvm.compiler.graph/src/org/graalvm/compiler/graph
org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64
org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64
org.graalvm.compiler.hotspot.lir.test/src/org/graalvm/compiler/hotspot/lir/test
BenchmarkCounterOverflowTest.javaExceedMaxOopMapStackOffset.javaMitigateExceedingMaxOopMapStackOffsetTest.java
org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc
org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test
BoxDeoptimizationTest.javaCheckGraalIntrinsics.javaCompilationWrapperTest.javaCompressedOopTest.javaHotSpotCryptoSubstitutionTest.javaHotSpotGraalManagementTest.javaJVMCIVersionCheckTest.javaNodeCostDumpUtil.java
org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot
CompilationContext.javaCompilationCounters.javaCompilationTask.javaCompilationWatchDog.javaCompilerConfigurationFactory.javaHotSpotGraalCompiler.javaHotSpotGraalServices.javaHotSpotReplacementsImpl.javaHotSpotTTYStreamProvider.javaIsGraalPredicateBase.javaJVMCIVersionCheck.java
meta
nodes
phases
replacements
org.graalvm.compiler.java/src/org/graalvm/compiler/java
org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64
org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64
org.graalvm.compiler.lir.jtt/src/org/graalvm/compiler/lir/jtt
org.graalvm.compiler.lir/src/org/graalvm/compiler/lir
org.graalvm.compiler.loop.test/src/org/graalvm/compiler/loop/test
org.graalvm.compiler.loop/src/org/graalvm/compiler/loop
org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes
@ -156,9 +156,10 @@ public final class HotSpotGraalManagement implements HotSpotGraalManagementRegis
|
||||
platformMBeanServer = ManagementFactory.getPlatformMBeanServer();
|
||||
process();
|
||||
}
|
||||
} catch (SecurityException e) {
|
||||
} catch (SecurityException | UnsatisfiedLinkError | NoClassDefFoundError | UnsupportedOperationException e) {
|
||||
// Without permission to find or create the MBeanServer,
|
||||
// we cannot process any Graal mbeans.
|
||||
// Various other errors can occur in the ManagementFactory (JDK-8076557)
|
||||
deferred = null;
|
||||
}
|
||||
} else {
|
||||
|
@ -171,4 +171,3 @@ public final class OptionsEncoder {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 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.api.directives.test;
|
||||
|
||||
import org.graalvm.compiler.api.directives.GraalDirectives;
|
||||
import org.graalvm.compiler.core.test.GraalCompilerTest;
|
||||
import org.graalvm.compiler.graph.iterators.NodeIterable;
|
||||
import org.graalvm.compiler.nodes.IfNode;
|
||||
import org.graalvm.compiler.nodes.StructuredGraph;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class ConstantProbablityBranchFoldingTest extends GraalCompilerTest {
|
||||
|
||||
public static int branchFoldingSnippet1() {
|
||||
if (GraalDirectives.injectBranchProbability(0.5, true)) {
|
||||
return 1;
|
||||
} else {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
public static int branchFoldingSnippet2() {
|
||||
if (GraalDirectives.injectBranchProbability(0.5, false)) {
|
||||
return 1;
|
||||
} else {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEarlyFolding1() {
|
||||
test("branchFoldingSnippet1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEarlyFolding2() {
|
||||
test("branchFoldingSnippet2");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void checkLowTierGraph(StructuredGraph graph) {
|
||||
NodeIterable<IfNode> ifNodes = graph.getNodes(IfNode.TYPE);
|
||||
Assert.assertEquals("IfNode count", 0, ifNodes.count());
|
||||
}
|
||||
}
|
@ -75,6 +75,9 @@ public class AArch64BitCountAssemblerTest extends AssemblerTest {
|
||||
AArch64MacroAssembler masm = new AArch64MacroAssembler(target);
|
||||
Register dst = registerConfig.getReturnRegister(JavaKind.Int);
|
||||
Register src = asRegister(cc.getArgument(0));
|
||||
// Generate a nop first as AArch64 Hotspot requires instruction at nmethod verified
|
||||
// entry to be a jump or nop. (See https://github.com/oracle/graal/issues/1439)
|
||||
masm.nop();
|
||||
RegisterArray registers = registerConfig.filterAllocatableRegisters(AArch64Kind.V64_BYTE, registerConfig.getAllocatableRegisters());
|
||||
masm.popcnt(size, dst, src, registers.get(registers.size() - 1));
|
||||
masm.ret(AArch64.lr);
|
||||
|
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 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.aarch64;
|
||||
|
||||
import org.graalvm.compiler.nodes.spi.LoweringProvider;
|
||||
|
||||
public interface AArch64LoweringProviderMixin extends LoweringProvider {
|
||||
|
||||
@Override
|
||||
default Integer smallestCompareWidth() {
|
||||
return 32;
|
||||
}
|
||||
|
||||
@Override
|
||||
default boolean supportBulkZeroing() {
|
||||
return false;
|
||||
}
|
||||
}
|
@ -80,9 +80,9 @@ public class AArch64ReadNode extends ReadNode {
|
||||
*/
|
||||
public static void replace(ReadNode readNode) {
|
||||
assert readNode.getUsageCount() == 1;
|
||||
assert readNode.getUsageAt(0) instanceof ZeroExtendNode || readNode.getUsageAt(0) instanceof SignExtendNode;
|
||||
assert readNode.usages().first() instanceof ZeroExtendNode || readNode.usages().first() instanceof SignExtendNode;
|
||||
|
||||
ValueNode usage = (ValueNode) readNode.getUsageAt(0);
|
||||
ValueNode usage = (ValueNode) readNode.usages().first();
|
||||
boolean isSigned = usage instanceof SignExtendNode;
|
||||
IntegerStamp accessStamp = ((IntegerStamp) readNode.getAccessStamp());
|
||||
|
||||
|
@ -49,7 +49,7 @@ public class AArch64ReadReplacementPhase extends Phase {
|
||||
if (node instanceof ReadNode) {
|
||||
ReadNode readNode = (ReadNode) node;
|
||||
if (readNode.hasExactlyOneUsage()) {
|
||||
Node usage = readNode.getUsageAt(0);
|
||||
Node usage = readNode.usages().first();
|
||||
if (usage instanceof ZeroExtendNode || usage instanceof SignExtendNode) {
|
||||
AArch64ReadNode.replace(readNode);
|
||||
}
|
||||
|
@ -24,8 +24,10 @@
|
||||
|
||||
package org.graalvm.compiler.core.aarch64;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
|
||||
import org.graalvm.compiler.debug.GraalError;
|
||||
import org.graalvm.compiler.java.DefaultSuitesCreator;
|
||||
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
|
||||
import org.graalvm.compiler.options.OptionValues;
|
||||
@ -37,24 +39,33 @@ import org.graalvm.compiler.phases.tiers.LowTierContext;
|
||||
import org.graalvm.compiler.phases.tiers.Suites;
|
||||
|
||||
public class AArch64SuitesCreator extends DefaultSuitesCreator {
|
||||
private final Class<? extends Phase> insertReadReplacementBefore;
|
||||
private final List<Class<? extends Phase>> insertReadReplacementBeforePositions;
|
||||
|
||||
public AArch64SuitesCreator(CompilerConfiguration compilerConfiguration, Plugins plugins, Class<? extends Phase> insertReadReplacementBefore) {
|
||||
public AArch64SuitesCreator(CompilerConfiguration compilerConfiguration, Plugins plugins, List<Class<? extends Phase>> insertReadReplacementBeforePositions) {
|
||||
super(compilerConfiguration, plugins);
|
||||
this.insertReadReplacementBefore = insertReadReplacementBefore;
|
||||
this.insertReadReplacementBeforePositions = insertReadReplacementBeforePositions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Suites createSuites(OptionValues options) {
|
||||
Suites suites = super.createSuites(options);
|
||||
|
||||
ListIterator<BasePhase<? super LowTierContext>> findPhase = suites.getLowTier().findPhase(insertReadReplacementBefore);
|
||||
// Put AArch64ReadReplacementPhase right before the SchedulePhase
|
||||
while (PhaseSuite.findNextPhase(findPhase, insertReadReplacementBefore)) {
|
||||
// Search for last occurrence of SchedulePhase
|
||||
ListIterator<BasePhase<? super LowTierContext>> findPhase = null;
|
||||
for (Class<? extends Phase> phase : insertReadReplacementBeforePositions) {
|
||||
findPhase = suites.getLowTier().findPhase(phase);
|
||||
if (findPhase != null) {
|
||||
// Put AArch64ReadReplacementPhase right before the requested phase
|
||||
while (PhaseSuite.findNextPhase(findPhase, phase)) {
|
||||
// Search for last occurrence of SchedulePhase
|
||||
}
|
||||
findPhase.previous();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (findPhase != null) {
|
||||
findPhase.add(new AArch64ReadReplacementPhase());
|
||||
} else {
|
||||
throw GraalError.shouldNotReachHere("Cannot find phase to insert AArch64ReadReplacementPhase");
|
||||
}
|
||||
findPhase.previous();
|
||||
findPhase.add(new AArch64ReadReplacementPhase());
|
||||
return suites;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2019, 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
|
||||
@ -143,7 +143,7 @@ public class ConstantStackMoveTest extends LIRTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runByte() throws Throwable {
|
||||
public void runByte() {
|
||||
runTest("testByte");
|
||||
}
|
||||
|
||||
@ -157,7 +157,7 @@ public class ConstantStackMoveTest extends LIRTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runShort() throws Throwable {
|
||||
public void runShort() {
|
||||
runTest("testShort");
|
||||
}
|
||||
|
||||
@ -171,7 +171,7 @@ public class ConstantStackMoveTest extends LIRTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runInt() throws Throwable {
|
||||
public void runInt() {
|
||||
runTest("testInt");
|
||||
}
|
||||
|
||||
@ -185,7 +185,7 @@ public class ConstantStackMoveTest extends LIRTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runLong() throws Throwable {
|
||||
public void runLong() {
|
||||
runTest("testLong");
|
||||
}
|
||||
|
||||
@ -199,7 +199,7 @@ public class ConstantStackMoveTest extends LIRTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runFloat() throws Throwable {
|
||||
public void runFloat() {
|
||||
runTest("testFloat");
|
||||
}
|
||||
|
||||
@ -213,7 +213,7 @@ public class ConstantStackMoveTest extends LIRTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runDouble() throws Throwable {
|
||||
public void runDouble() {
|
||||
runTest("testDouble");
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2019, 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
|
||||
@ -113,7 +113,7 @@ public class StackStoreTest extends LIRTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void run0() throws Throwable {
|
||||
public void run0() {
|
||||
runTest("test0", 0xDEADDEAD);
|
||||
}
|
||||
|
||||
@ -122,7 +122,7 @@ public class StackStoreTest extends LIRTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void run1() throws Throwable {
|
||||
public void run1() {
|
||||
runTest("test1", 0xDEADDEAD);
|
||||
}
|
||||
|
||||
@ -131,7 +131,7 @@ public class StackStoreTest extends LIRTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void run2() throws Throwable {
|
||||
public void run2() {
|
||||
runTest("test2", 0xDEADDEAD);
|
||||
}
|
||||
|
||||
|
@ -126,6 +126,7 @@ import org.graalvm.compiler.lir.amd64.AMD64Ternary;
|
||||
import org.graalvm.compiler.lir.amd64.AMD64Unary;
|
||||
import org.graalvm.compiler.lir.amd64.AMD64ZeroMemoryOp;
|
||||
import org.graalvm.compiler.lir.amd64.vector.AMD64VectorBinary;
|
||||
import org.graalvm.compiler.lir.amd64.vector.AMD64VectorBinary.AVXBinaryConstFloatOp;
|
||||
import org.graalvm.compiler.lir.amd64.vector.AMD64VectorBinary.AVXBinaryOp;
|
||||
import org.graalvm.compiler.lir.amd64.vector.AMD64VectorUnary;
|
||||
import org.graalvm.compiler.lir.gen.ArithmeticLIRGenerator;
|
||||
@ -1360,9 +1361,13 @@ public class AMD64ArithmeticLIRGenerator extends ArithmeticLIRGenerator implemen
|
||||
}
|
||||
}
|
||||
|
||||
private Variable emitBinary(LIRKind resultKind, VexRVMOp op, Value a, Value b) {
|
||||
protected Variable emitBinary(LIRKind resultKind, VexRVMOp op, Value a, Value b) {
|
||||
Variable result = getLIRGen().newVariable(resultKind);
|
||||
getLIRGen().append(new AVXBinaryOp(op, getRegisterSize(result), result, asAllocatable(a), asAllocatable(b)));
|
||||
if (b instanceof ConstantValue && (b.getPlatformKind() == AMD64Kind.SINGLE || b.getPlatformKind() == AMD64Kind.DOUBLE)) {
|
||||
getLIRGen().append(new AVXBinaryConstFloatOp(op, getRegisterSize(result), result, asAllocatable(a), (ConstantValue) b));
|
||||
} else {
|
||||
getLIRGen().append(new AVXBinaryOp(op, getRegisterSize(result), result, asAllocatable(a), asAllocatable(b)));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -47,8 +47,8 @@ import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic;
|
||||
import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MIOp;
|
||||
import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RMOp;
|
||||
import org.graalvm.compiler.asm.amd64.AMD64Assembler.ConditionFlag;
|
||||
import org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize;
|
||||
import org.graalvm.compiler.asm.amd64.AMD64Assembler.SSEOp;
|
||||
import org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize;
|
||||
import org.graalvm.compiler.core.common.LIRKind;
|
||||
import org.graalvm.compiler.core.common.NumUtil;
|
||||
import org.graalvm.compiler.core.common.calc.Condition;
|
||||
@ -80,10 +80,10 @@ import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.CondSetOp;
|
||||
import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.FloatBranchOp;
|
||||
import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.FloatCondMoveOp;
|
||||
import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.FloatCondSetOp;
|
||||
import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.HashTableSwitchOp;
|
||||
import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.ReturnOp;
|
||||
import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.StrategySwitchOp;
|
||||
import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.TableSwitchOp;
|
||||
import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.HashTableSwitchOp;
|
||||
import org.graalvm.compiler.lir.amd64.AMD64LFenceOp;
|
||||
import org.graalvm.compiler.lir.amd64.AMD64Move;
|
||||
import org.graalvm.compiler.lir.amd64.AMD64Move.CompareAndSwapOp;
|
||||
|
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 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.amd64;
|
||||
|
||||
import org.graalvm.compiler.nodes.spi.LoweringProvider;
|
||||
|
||||
public interface AMD64LoweringProviderMixin extends LoweringProvider {
|
||||
|
||||
@Override
|
||||
default Integer smallestCompareWidth() {
|
||||
return 8;
|
||||
}
|
||||
|
||||
@Override
|
||||
default boolean supportBulkZeroing() {
|
||||
return true;
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2019, 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
|
||||
@ -50,6 +50,7 @@ import jdk.vm.ci.code.Register;
|
||||
import jdk.vm.ci.meta.AllocatableValue;
|
||||
import jdk.vm.ci.meta.Constant;
|
||||
import jdk.vm.ci.meta.JavaConstant;
|
||||
import jdk.vm.ci.meta.PrimitiveConstant;
|
||||
import jdk.vm.ci.meta.Value;
|
||||
|
||||
public abstract class AMD64MoveFactory extends AMD64MoveFactoryBase {
|
||||
@ -65,6 +66,9 @@ public abstract class AMD64MoveFactory extends AMD64MoveFactoryBase {
|
||||
switch (c.getJavaKind()) {
|
||||
case Long:
|
||||
return NumUtil.isInt(c.asLong());
|
||||
case Float:
|
||||
case Double:
|
||||
return false;
|
||||
case Object:
|
||||
return c.isNull();
|
||||
default:
|
||||
@ -74,6 +78,12 @@ public abstract class AMD64MoveFactory extends AMD64MoveFactoryBase {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mayEmbedConstantLoad(Constant constant) {
|
||||
// Only consider not inlineable constants here.
|
||||
return constant instanceof PrimitiveConstant && ((PrimitiveConstant) constant).getJavaKind().isNumericFloat();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean allowConstantToStackMove(Constant constant) {
|
||||
if (constant instanceof DataPointerConstant) {
|
||||
|
@ -289,4 +289,6 @@ public final class GraalOptions {
|
||||
@Option(help = "If applicable, use bulk zeroing instructions when the zeroing size in bytes exceeds this threshold.", type = OptionType.Expert)
|
||||
public static final OptionKey<Integer> MinimalBulkZeroingSize = new OptionKey<>(2048);
|
||||
|
||||
@Option(help = "Alignment in bytes for loop header blocks.", type = OptionType.Expert)
|
||||
public static final OptionKey<Integer> LoopHeaderAlignment = new OptionKey<>(16);
|
||||
}
|
||||
|
@ -32,6 +32,8 @@ import static org.graalvm.compiler.core.common.util.TypeConversion.asU2;
|
||||
import static org.graalvm.compiler.core.common.util.TypeConversion.asU4;
|
||||
import static org.graalvm.compiler.serviceprovider.GraalUnsafeAccess.getUnsafe;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.graalvm.compiler.core.common.calc.UnsignedMath;
|
||||
|
||||
import sun.misc.Unsafe;
|
||||
@ -103,6 +105,17 @@ public abstract class UnsafeArrayTypeWriter implements TypeWriter {
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Copies the buffer into the provided ByteBuffer at its current position. */
|
||||
public final ByteBuffer toByteBuffer(ByteBuffer buffer) {
|
||||
assert buffer.remaining() <= totalSize;
|
||||
int initialPos = buffer.position();
|
||||
for (Chunk cur = firstChunk; cur != null; cur = cur.next) {
|
||||
buffer.put(cur.data, 0, cur.size);
|
||||
}
|
||||
assert buffer.position() - initialPos == totalSize;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void putS1(long value) {
|
||||
long offset = writeOffset(Byte.BYTES);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2009, 2019, 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
|
||||
|
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 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.sparc;
|
||||
|
||||
import org.graalvm.compiler.nodes.spi.LoweringProvider;
|
||||
|
||||
public interface SparcLoweringProviderMixin extends LoweringProvider {
|
||||
|
||||
@Override
|
||||
default Integer smallestCompareWidth() {
|
||||
return 32;
|
||||
}
|
||||
|
||||
@Override
|
||||
default boolean supportBulkZeroing() {
|
||||
return false;
|
||||
}
|
||||
}
|
@ -63,4 +63,3 @@ public class ConditionalEliminationPiTest extends ConditionalEliminationTestBase
|
||||
test("testSnippet1", 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
package org.graalvm.compiler.core.test;
|
||||
|
||||
import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind;
|
||||
import org.junit.Test;
|
||||
|
||||
public class ConditionalNodeTest extends GraalCompilerTest {
|
||||
@ -106,4 +107,23 @@ public class ConditionalNodeTest extends GraalCompilerTest {
|
||||
sink0 = 1;
|
||||
return Math.min(-1, value);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test4() {
|
||||
test("conditionalTest4", this, 0);
|
||||
test("conditionalTest4", this, 1);
|
||||
}
|
||||
|
||||
int a;
|
||||
InvokeKind b;
|
||||
|
||||
public static int conditionalTest4(ConditionalNodeTest node, int a) {
|
||||
if (a == 1) {
|
||||
node.b = InvokeKind.Virtual;
|
||||
} else {
|
||||
node.b = InvokeKind.Special;
|
||||
}
|
||||
node.a = a;
|
||||
return a;
|
||||
}
|
||||
}
|
||||
|
@ -53,17 +53,18 @@ public class DumpPathTest extends GraalCompilerTest {
|
||||
String[] extensions = new String[]{".cfg", ".bgv", ".graph-strings"};
|
||||
EconomicMap<OptionKey<?>, Object> overrides = OptionValues.newOptionMap();
|
||||
overrides.put(DebugOptions.DumpPath, dumpDirectoryPath.toString());
|
||||
overrides.put(DebugOptions.PrintCFG, true);
|
||||
overrides.put(DebugOptions.PrintGraph, PrintGraphTarget.File);
|
||||
overrides.put(DebugOptions.PrintCanonicalGraphStrings, true);
|
||||
overrides.put(DebugOptions.Dump, "*");
|
||||
|
||||
// Generate dump files.
|
||||
test(new OptionValues(getInitialOptions(), overrides), "snippet");
|
||||
// Check that Ideal files got created, in the right place.
|
||||
// Check that IGV files got created, in the right place.
|
||||
checkForFiles(dumpDirectoryPath, extensions);
|
||||
|
||||
// Clean up the generated files.
|
||||
scrubDirectory(dumpDirectoryPath);
|
||||
removeDirectory(dumpDirectoryPath);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -92,24 +93,4 @@ public class DumpPathTest extends GraalCompilerTest {
|
||||
assertTrue(paths[0].equals(paths[i]), paths[0] + " != " + paths[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the temporary directory.
|
||||
*/
|
||||
private static void scrubDirectory(Path directoryPath) {
|
||||
try {
|
||||
try (DirectoryStream<Path> stream = Files.newDirectoryStream(directoryPath)) {
|
||||
for (Path filePath : stream) {
|
||||
if (Files.isRegularFile(filePath)) {
|
||||
Files.delete(filePath);
|
||||
} else if (Files.isDirectory(filePath)) {
|
||||
scrubDirectory(filePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
Files.delete(directoryPath);
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -29,7 +29,6 @@ import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||
import jdk.vm.ci.meta.ResolvedJavaType;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
public class FindUniqueConcreteMethodBugTest extends GraalCompilerTest {
|
||||
@ -44,7 +43,6 @@ public class FindUniqueConcreteMethodBugTest extends GraalCompilerTest {
|
||||
* {@link PersonImpl#getName()} and {@link Tenant#getName()}).
|
||||
*/
|
||||
@Test
|
||||
@Ignore("fix HotSpotResolvedObjectTypeImpl.findUniqueConcreteMethod")
|
||||
public void test() throws NoSuchMethodException {
|
||||
ResolvedJavaMethod ifaceMethod = getMetaAccess().lookupJavaMethod(Person.class.getDeclaredMethod("getName"));
|
||||
|
||||
@ -64,9 +62,8 @@ public class FindUniqueConcreteMethodBugTest extends GraalCompilerTest {
|
||||
// this causes a VM crash as getLabelLength() directly invokes PersonImpl.getName().
|
||||
test("getLabelLength", tenant);
|
||||
|
||||
ResolvedJavaMethod expected = null;
|
||||
AssumptionResult<ResolvedJavaMethod> actual = getMetaAccess().lookupJavaType(AbstractPerson.class).findUniqueConcreteMethod(ifaceMethod);
|
||||
Assert.assertEquals(expected, actual.getResult());
|
||||
Assert.assertNull(String.valueOf(actual), actual);
|
||||
|
||||
}
|
||||
|
||||
|
@ -1116,8 +1116,14 @@ public abstract class GraalCompilerTest extends GraalTest {
|
||||
return graph;
|
||||
}
|
||||
|
||||
@SuppressWarnings("try")
|
||||
protected void applyFrontEnd(StructuredGraph graph) {
|
||||
GraalCompiler.emitFrontEnd(getProviders(), getBackend(), graph, getDefaultGraphBuilderSuite(), getOptimisticOptimizations(), graph.getProfilingInfo(), createSuites(graph.getOptions()));
|
||||
DebugContext debug = graph.getDebug();
|
||||
try (DebugContext.Scope s = debug.scope("FrontEnd", graph)) {
|
||||
GraalCompiler.emitFrontEnd(getProviders(), getBackend(), graph, getDefaultGraphBuilderSuite(), getOptimisticOptimizations(), graph.getProfilingInfo(), createSuites(graph.getOptions()));
|
||||
} catch (Throwable e) {
|
||||
throw debug.handle(e);
|
||||
}
|
||||
}
|
||||
|
||||
protected StructuredGraph lastCompiledGraph;
|
||||
|
491
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SwitchFoldingTest.java
Normal file
491
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SwitchFoldingTest.java
Normal file
@ -0,0 +1,491 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 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.graalvm.compiler.debug.DebugContext;
|
||||
import org.graalvm.compiler.nodes.StructuredGraph;
|
||||
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
|
||||
import org.junit.Test;
|
||||
|
||||
public class SwitchFoldingTest extends GraalCompilerTest {
|
||||
|
||||
private static final String REFERENCE_SNIPPET = "referenceSnippet";
|
||||
private static final String REFERENCE_SNIPPET_2 = "reference2Snippet";
|
||||
private static final String REFERENCE_SNIPPET_3 = "reference3Snippet";
|
||||
private static final String REFERENCE_SNIPPET_4 = "reference4Snippet";
|
||||
private static final String REFERENCE_SNIPPET_5 = "reference5Snippet";
|
||||
|
||||
public static int referenceSnippet(int a) {
|
||||
switch (a) {
|
||||
case 0:
|
||||
return 10;
|
||||
case 1:
|
||||
return 5;
|
||||
case 2:
|
||||
return 3;
|
||||
case 3:
|
||||
return 11;
|
||||
case 4:
|
||||
return 14;
|
||||
case 5:
|
||||
return 2;
|
||||
case 6:
|
||||
return 1;
|
||||
case 7:
|
||||
return 0;
|
||||
case 8:
|
||||
return 7;
|
||||
default:
|
||||
return 6;
|
||||
}
|
||||
}
|
||||
|
||||
public static int reference2Snippet(int a) {
|
||||
switch (a) {
|
||||
case 0:
|
||||
return 4;
|
||||
case 1:
|
||||
case 2:
|
||||
return 1;
|
||||
case 3:
|
||||
return 6;
|
||||
default:
|
||||
return 7;
|
||||
}
|
||||
}
|
||||
|
||||
public static int reference3Snippet(int a) {
|
||||
switch (a) {
|
||||
case 0:
|
||||
return 4;
|
||||
case 1:
|
||||
case 2:
|
||||
case 4:
|
||||
return 6;
|
||||
case 6:
|
||||
case 7:
|
||||
default:
|
||||
return 7;
|
||||
}
|
||||
}
|
||||
|
||||
public static int test1Snippet(int a) {
|
||||
if (a == 0) {
|
||||
return 10;
|
||||
} else if (a == 1) {
|
||||
return 5;
|
||||
} else if (a == 2) {
|
||||
return 3;
|
||||
} else if (a == 3) {
|
||||
return 11;
|
||||
} else if (a == 4) {
|
||||
return 14;
|
||||
} else if (a == 5) {
|
||||
return 2;
|
||||
} else if (a == 6) {
|
||||
return 1;
|
||||
} else if (a == 7) {
|
||||
return 0;
|
||||
} else if (a == 8) {
|
||||
return 7;
|
||||
} else {
|
||||
return 6;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test1() {
|
||||
test1("test1Snippet");
|
||||
}
|
||||
|
||||
public static int test2Snippet(int a) {
|
||||
switch (a) {
|
||||
case 0:
|
||||
return 10;
|
||||
case 1:
|
||||
return 5;
|
||||
case 2:
|
||||
return 3;
|
||||
case 3:
|
||||
return 11;
|
||||
case 4:
|
||||
return 14;
|
||||
default:
|
||||
switch (a) {
|
||||
case 5:
|
||||
return 2;
|
||||
case 6:
|
||||
return 1;
|
||||
case 7:
|
||||
return 0;
|
||||
case 8:
|
||||
return 7;
|
||||
default:
|
||||
return 6;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test2() {
|
||||
test1("test2Snippet");
|
||||
}
|
||||
|
||||
public static int test3Snippet(int a) {
|
||||
switch (a) {
|
||||
case 0:
|
||||
return 10;
|
||||
default:
|
||||
switch (a) {
|
||||
case 1:
|
||||
return 5;
|
||||
default:
|
||||
switch (a) {
|
||||
case 2:
|
||||
return 3;
|
||||
default:
|
||||
switch (a) {
|
||||
case 3:
|
||||
return 11;
|
||||
default:
|
||||
switch (a) {
|
||||
case 4:
|
||||
return 14;
|
||||
default:
|
||||
switch (a) {
|
||||
case 5:
|
||||
return 2;
|
||||
default:
|
||||
switch (a) {
|
||||
case 6:
|
||||
return 1;
|
||||
default:
|
||||
switch (a) {
|
||||
case 7:
|
||||
return 0;
|
||||
default:
|
||||
switch (a) {
|
||||
case 8:
|
||||
return 7;
|
||||
default:
|
||||
return 6;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test3() {
|
||||
test1("test3Snippet");
|
||||
}
|
||||
|
||||
public static int test4Snippet(int a) {
|
||||
switch (a) {
|
||||
case 0:
|
||||
return 10;
|
||||
case 1:
|
||||
return 5;
|
||||
case 2:
|
||||
return 3;
|
||||
case 3:
|
||||
return 11;
|
||||
case 4:
|
||||
return 14;
|
||||
case 5:
|
||||
return 2;
|
||||
case 6:
|
||||
return 1;
|
||||
default:
|
||||
if (a == 7) {
|
||||
return 0;
|
||||
} else if (a == 8) {
|
||||
return 7;
|
||||
} else {
|
||||
return 6;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test4() {
|
||||
test1("test4Snippet");
|
||||
}
|
||||
|
||||
public static int test5Snippet(int a) {
|
||||
switch (a) {
|
||||
case 0:
|
||||
return 10;
|
||||
default:
|
||||
switch (a) {
|
||||
case 1:
|
||||
return 5;
|
||||
default:
|
||||
switch (a) {
|
||||
case 2:
|
||||
return 3;
|
||||
default:
|
||||
switch (a) {
|
||||
case 3:
|
||||
return 11;
|
||||
default:
|
||||
switch (a) {
|
||||
case 4:
|
||||
return 14;
|
||||
default:
|
||||
switch (a) {
|
||||
case 5:
|
||||
return 2;
|
||||
default:
|
||||
switch (a) {
|
||||
case 6:
|
||||
return 1;
|
||||
default:
|
||||
if (a == 7) {
|
||||
return 0;
|
||||
} else if (a == 8) {
|
||||
return 7;
|
||||
} else {
|
||||
return 6;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test5() {
|
||||
test1("test5Snippet");
|
||||
}
|
||||
|
||||
public static int test6Snippet(int a) {
|
||||
if (a == 0) {
|
||||
return 10;
|
||||
} else {
|
||||
switch (a) {
|
||||
case 1:
|
||||
return 5;
|
||||
default:
|
||||
if (a == 2) {
|
||||
return 3;
|
||||
} else if (a == 3) {
|
||||
return 11;
|
||||
} else {
|
||||
switch (a) {
|
||||
case 4:
|
||||
return 14;
|
||||
case 5:
|
||||
return 2;
|
||||
case 6:
|
||||
return 1;
|
||||
default:
|
||||
if (a == 7) {
|
||||
return 0;
|
||||
} else if (a == 8) {
|
||||
return 7;
|
||||
} else {
|
||||
return 6;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test6() {
|
||||
test1("test6Snippet");
|
||||
}
|
||||
|
||||
public static int test7Snippet(int a) {
|
||||
if (a == 0) {
|
||||
return 4;
|
||||
} else {
|
||||
switch (a) {
|
||||
case 1:
|
||||
case 2:
|
||||
return 1;
|
||||
case 3:
|
||||
return 6;
|
||||
default:
|
||||
return 7;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test7() {
|
||||
test2("test7Snippet");
|
||||
}
|
||||
|
||||
public static int test8Snippet(int a) {
|
||||
switch (a) {
|
||||
case 0:
|
||||
return 4;
|
||||
case 1:
|
||||
case 2:
|
||||
case 7:
|
||||
default:
|
||||
switch (a) {
|
||||
case 2:
|
||||
case 6:
|
||||
default:
|
||||
switch (a) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 4:
|
||||
return 6;
|
||||
default:
|
||||
return 7;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test8() {
|
||||
test3("test8Snippet");
|
||||
}
|
||||
|
||||
public static int reference4Snippet(int a) {
|
||||
switch (a) {
|
||||
case 0:
|
||||
return 4;
|
||||
case 1:
|
||||
case 2:
|
||||
case 4:
|
||||
return 6;
|
||||
case 6:
|
||||
return 7;
|
||||
case 7:
|
||||
return 7;
|
||||
default:
|
||||
return 7;
|
||||
}
|
||||
}
|
||||
|
||||
public static int test9Snippet(int a) {
|
||||
switch (a) {
|
||||
case 0:
|
||||
return 4;
|
||||
case 1:
|
||||
case 2:
|
||||
case 4:
|
||||
return 6;
|
||||
case 6:
|
||||
case 7:
|
||||
default:
|
||||
if (a == 6) {
|
||||
return 7;
|
||||
} else if (a == 7) {
|
||||
return 7;
|
||||
} else {
|
||||
return 7;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test9() {
|
||||
test4("test9Snippet");
|
||||
}
|
||||
|
||||
public static int reference5Snippet(int a) {
|
||||
switch (a) {
|
||||
case 0:
|
||||
return 4;
|
||||
case 1:
|
||||
return 1;
|
||||
case 2:
|
||||
return 1;
|
||||
case 3:
|
||||
return 6;
|
||||
default:
|
||||
return 7;
|
||||
}
|
||||
}
|
||||
|
||||
public static int test10Snippet(int a) {
|
||||
if (a == 0) {
|
||||
return 4;
|
||||
} else {
|
||||
if (a == 1 || a == 2) {
|
||||
return 1;
|
||||
} else {
|
||||
switch (a) {
|
||||
case 3:
|
||||
return 6;
|
||||
default:
|
||||
return 7;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test10() {
|
||||
test5("test10Snippet");
|
||||
}
|
||||
|
||||
private void test1(String snippet) {
|
||||
test(snippet, REFERENCE_SNIPPET);
|
||||
}
|
||||
|
||||
private void test2(String snippet) {
|
||||
test(snippet, REFERENCE_SNIPPET_2);
|
||||
}
|
||||
|
||||
private void test3(String snippet) {
|
||||
test(snippet, REFERENCE_SNIPPET_3);
|
||||
}
|
||||
|
||||
private void test4(String snippet) {
|
||||
test(snippet, REFERENCE_SNIPPET_4);
|
||||
}
|
||||
|
||||
private void test5(String snippet) {
|
||||
test(snippet, REFERENCE_SNIPPET_5);
|
||||
}
|
||||
|
||||
private void test(String snippet, String ref) {
|
||||
StructuredGraph graph = parseEager(snippet, StructuredGraph.AllowAssumptions.YES);
|
||||
DebugContext debug = graph.getDebug();
|
||||
debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph");
|
||||
new CanonicalizerPhase().apply(graph, getProviders());
|
||||
StructuredGraph referenceGraph = parseEager(ref, StructuredGraph.AllowAssumptions.YES);
|
||||
assertEquals(referenceGraph, graph);
|
||||
}
|
||||
}
|
@ -45,10 +45,10 @@ public abstract class BackendTest extends GraalCompilerTest {
|
||||
}
|
||||
|
||||
@SuppressWarnings("try")
|
||||
protected LIRGenerationResult getLIRGenerationResult(final StructuredGraph graph) {
|
||||
protected LIRGenerationResult getLIRGenerationResult(final StructuredGraph graph, OptimisticOptimizations optimizations) {
|
||||
DebugContext debug = graph.getDebug();
|
||||
try (DebugContext.Scope s = debug.scope("FrontEnd")) {
|
||||
GraalCompiler.emitFrontEnd(getProviders(), getBackend(), graph, getDefaultGraphBuilderSuite(), OptimisticOptimizations.NONE, graph.getProfilingInfo(), createSuites(graph.getOptions()));
|
||||
GraalCompiler.emitFrontEnd(getProviders(), getBackend(), graph, getDefaultGraphBuilderSuite(), optimizations, graph.getProfilingInfo(), createSuites(graph.getOptions()));
|
||||
} catch (Throwable e) {
|
||||
throw debug.handle(e);
|
||||
}
|
||||
@ -57,4 +57,7 @@ public abstract class BackendTest extends GraalCompilerTest {
|
||||
return lirGen;
|
||||
}
|
||||
|
||||
protected LIRGenerationResult getLIRGenerationResult(final StructuredGraph graph) {
|
||||
return getLIRGenerationResult(graph, OptimisticOptimizations.NONE);
|
||||
}
|
||||
}
|
||||
|
@ -302,10 +302,16 @@ public abstract class CompilationWrapper<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls {@link System#exit(int)} in the runtime embedding the Graal compiler. This will be a
|
||||
* different runtime than Graal's runtime in the case of libgraal.
|
||||
*/
|
||||
protected abstract void exitHostVM(int status);
|
||||
|
||||
private void maybeExitVM(ExceptionAction action) {
|
||||
if (action == ExitVM) {
|
||||
TTY.println("Exiting VM after retry compilation of " + this);
|
||||
System.exit(-1);
|
||||
exitHostVM(-1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -156,10 +156,6 @@ public class DebugInfoBuilder {
|
||||
}
|
||||
assert checkValues(vobjValue.getType(), values, slotKinds);
|
||||
vobjValue.setValues(values, slotKinds);
|
||||
|
||||
if (vobjNode instanceof VirtualBoxingNode) {
|
||||
GraalServices.markVirtualObjectAsAutoBox(vobjValue);
|
||||
}
|
||||
}
|
||||
|
||||
virtualObjectsArray = new VirtualObject[virtualObjects.size()];
|
||||
@ -323,7 +319,8 @@ public class DebugInfoBuilder {
|
||||
assert obj.entryCount() == 0 || state instanceof VirtualObjectState;
|
||||
VirtualObject vobject = virtualObjects.get(obj);
|
||||
if (vobject == null) {
|
||||
vobject = VirtualObject.get(obj.type(), virtualObjects.size());
|
||||
boolean isAutoBox = obj instanceof VirtualBoxingNode;
|
||||
vobject = GraalServices.createVirtualObject(obj.type(), virtualObjects.size(), isAutoBox);
|
||||
virtualObjects.put(obj, vobject);
|
||||
pendingVirtualObjects.add(obj);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2009, 2019, 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
|
||||
|
@ -257,7 +257,6 @@ public abstract class Backend implements TargetProvider, ValueKindFactory<LIRKin
|
||||
* @throws BailoutException if the code installation failed
|
||||
*/
|
||||
public InstalledCode createDefaultInstalledCode(DebugContext debug, ResolvedJavaMethod method, CompilationResult compilationResult) {
|
||||
System.out.println(compilationResult.getSpeculationLog());
|
||||
return createInstalledCode(debug, method, compilationResult, null, true);
|
||||
}
|
||||
|
||||
|
@ -818,22 +818,24 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface {
|
||||
|
||||
private void replaceAtMatchingUsages(Node other, Predicate<Node> filter, Node toBeDeleted) {
|
||||
if (filter == null) {
|
||||
fail("filter cannot be null");
|
||||
throw fail("filter cannot be null");
|
||||
}
|
||||
checkReplaceWith(other);
|
||||
int i = 0;
|
||||
while (i < this.getUsageCount()) {
|
||||
int usageCount = this.getUsageCount();
|
||||
while (i < usageCount) {
|
||||
Node usage = this.getUsageAt(i);
|
||||
if (filter.test(usage)) {
|
||||
replaceAtUsage(other, toBeDeleted, usage);
|
||||
this.movUsageFromEndTo(i);
|
||||
usageCount--;
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Node getUsageAt(int index) {
|
||||
private Node getUsageAt(int index) {
|
||||
if (index == 0) {
|
||||
return this.usage0;
|
||||
} else if (index == 1) {
|
||||
@ -848,14 +850,35 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface {
|
||||
replaceAtMatchingUsages(other, usagePredicate, null);
|
||||
}
|
||||
|
||||
private void replaceAtUsagePos(Node other, Node usage, Position pos) {
|
||||
pos.initialize(usage, other);
|
||||
maybeNotifyInputChanged(usage);
|
||||
if (other != null) {
|
||||
other.addUsage(usage);
|
||||
}
|
||||
}
|
||||
|
||||
public void replaceAtUsages(InputType type, Node other) {
|
||||
checkReplaceWith(other);
|
||||
for (Node usage : usages().snapshot()) {
|
||||
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()) {
|
||||
if (pos.getInputType() == type && pos.get(usage) == this) {
|
||||
pos.set(usage, other);
|
||||
replaceAtUsagePos(other, usage, pos);
|
||||
this.movUsageFromEndTo(i);
|
||||
usageCount--;
|
||||
continue usages;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if (hasNoUsages()) {
|
||||
maybeNotifyZeroUsages(this);
|
||||
}
|
||||
}
|
||||
|
||||
@ -913,6 +936,14 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface {
|
||||
}
|
||||
}
|
||||
|
||||
public void replaceFirstInput(Node oldInput, Node newInput, InputType type) {
|
||||
for (Position pos : inputPositions()) {
|
||||
if (pos.getInputType() == type && pos.get(this) == oldInput) {
|
||||
pos.set(this, newInput);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void clearInputs() {
|
||||
assert assertFalse(isDeleted(), "cannot clear inputs of deleted node");
|
||||
getNodeClass().unregisterAtInputsAsUsage(this);
|
||||
@ -1059,6 +1090,8 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface {
|
||||
assertFalse(input.isDeleted(), "input was deleted %s", input);
|
||||
assertTrue(input.isAlive(), "input is not alive yet, i.e., it was not yet added to the graph");
|
||||
assertTrue(pos.getInputType() == InputType.Unchecked || input.isAllowedUsageType(pos.getInputType()), "invalid usage type %s %s", input, pos.getInputType());
|
||||
Class<?> expectedType = pos.getType();
|
||||
assertTrue(expectedType.isAssignableFrom(input.getClass()), "Invalid input type for %s: expected a %s but was a %s", pos, expectedType, input.getClass());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
@ -126,7 +126,7 @@ public final class NodeClass<T> extends FieldIntrospection<T> {
|
||||
field.setAccessible(true);
|
||||
return (NodeClass<T>) field.get(null);
|
||||
} catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException e) {
|
||||
throw new RuntimeException(e);
|
||||
throw new RuntimeException("Could not load Graal NodeClass TYPE field for " + clazz, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -127,6 +127,7 @@ public class NodeMap<T> extends NodeIdAccessor implements EconomicMap<Node, T> {
|
||||
private boolean check(Node node) {
|
||||
assert node.graph() == graph : String.format("%s is not part of the graph", node);
|
||||
assert !isNew(node) : "this node was added to the graph after creating the node map : " + node;
|
||||
assert node.isAlive() : "this node is not alive: " + node;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -146,4 +146,12 @@ public final class Position {
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
public Class<?> getType() {
|
||||
if (index < edges.getDirectCount()) {
|
||||
return edges.getType(index);
|
||||
} else {
|
||||
return Node.class;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -49,6 +49,7 @@ import org.graalvm.compiler.core.common.LIRKind;
|
||||
import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig;
|
||||
import org.graalvm.compiler.core.common.spi.ForeignCallLinkage;
|
||||
import org.graalvm.compiler.core.gen.LIRGenerationProvider;
|
||||
import org.graalvm.compiler.debug.DebugContext;
|
||||
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
|
||||
import org.graalvm.compiler.hotspot.HotSpotDataBuilder;
|
||||
import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
|
||||
@ -72,12 +73,16 @@ import org.graalvm.compiler.lir.gen.LIRGenerationResult;
|
||||
import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
|
||||
import org.graalvm.compiler.nodes.StructuredGraph;
|
||||
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
|
||||
import org.graalvm.compiler.serviceprovider.GraalUnsafeAccess;
|
||||
|
||||
import jdk.vm.ci.aarch64.AArch64Kind;
|
||||
import jdk.vm.ci.code.CallingConvention;
|
||||
import jdk.vm.ci.code.CompilationRequest;
|
||||
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;
|
||||
@ -85,6 +90,8 @@ import jdk.vm.ci.meta.JavaKind;
|
||||
import jdk.vm.ci.meta.JavaType;
|
||||
import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||
|
||||
import sun.misc.Unsafe;
|
||||
|
||||
/**
|
||||
* HotSpot AArch64 specific backend.
|
||||
*/
|
||||
@ -126,6 +133,46 @@ public class AArch64HotSpotBackend extends HotSpotHostBackend implements LIRGene
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public InstalledCode createInstalledCode(DebugContext debug,
|
||||
ResolvedJavaMethod method,
|
||||
CompilationRequest compilationRequest,
|
||||
CompilationResult compilationResult,
|
||||
InstalledCode predefinedInstalledCode,
|
||||
boolean isDefault,
|
||||
Object[] context) {
|
||||
boolean isStub = (method == null);
|
||||
boolean isAOT = compilationResult.isImmutablePIC();
|
||||
if (!isStub && !isAOT) {
|
||||
// Non-stub compilation results are installed into HotSpot as nmethods. As AArch64 has
|
||||
// a constraint that the instruction at nmethod verified entry point should be a nop or
|
||||
// jump, AArch64HotSpotBackend always generate a nop placeholder before the code body
|
||||
// for non-AOT compilations. See AArch64HotSpotBackend.emitInvalidatePlaceholder(). This
|
||||
// assert checks if the nop placeholder is generated at all required places, including
|
||||
// in manually assembled code in CodeGenTest cases.
|
||||
assert hasInvalidatePlaceholder(compilationResult);
|
||||
}
|
||||
return super.createInstalledCode(debug, method, compilationRequest, compilationResult, predefinedInstalledCode, isDefault, context);
|
||||
}
|
||||
|
||||
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) {
|
||||
// The nmethod verified entry is located at some pc offset.
|
||||
verifiedEntryOffset = mark.pcOffset;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Unsafe unsafe = GraalUnsafeAccess.getUnsafe();
|
||||
int instruction = unsafe.getIntVolatile(targetCode, unsafe.arrayBaseOffset(byte[].class) + verifiedEntryOffset);
|
||||
AArch64MacroAssembler masm = new AArch64MacroAssembler(getTarget());
|
||||
masm.nop();
|
||||
return instruction == masm.getInt(0);
|
||||
}
|
||||
|
||||
private class HotSpotFrameContext implements FrameContext {
|
||||
final boolean isStub;
|
||||
|
||||
|
@ -29,6 +29,7 @@ import static jdk.vm.ci.aarch64.AArch64.sp;
|
||||
import static jdk.vm.ci.common.InitTimer.timer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.graalvm.compiler.bytecode.BytecodeProvider;
|
||||
@ -193,7 +194,7 @@ public class AArch64HotSpotBackendFactory extends HotSpotBackendFactory {
|
||||
|
||||
protected HotSpotSuitesProvider createSuites(GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, CompilerConfiguration compilerConfiguration, Plugins plugins,
|
||||
@SuppressWarnings("unused") Replacements replacements) {
|
||||
AArch64SuitesCreator suitesCreator = new AArch64SuitesCreator(compilerConfiguration, plugins, SchedulePhase.class);
|
||||
AArch64SuitesCreator suitesCreator = new AArch64SuitesCreator(compilerConfiguration, plugins, Arrays.asList(SchedulePhase.class));
|
||||
Phase addressLoweringPhase = new AddressLoweringByUsePhase(new AArch64AddressLoweringByUse(new AArch64LIRKindTool()));
|
||||
return new AddressLoweringHotSpotSuitesProvider(suitesCreator, config, runtime, addressLoweringPhase);
|
||||
}
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
package org.graalvm.compiler.hotspot.aarch64;
|
||||
|
||||
import org.graalvm.compiler.core.aarch64.AArch64LoweringProviderMixin;
|
||||
import org.graalvm.compiler.core.common.spi.ForeignCallsProvider;
|
||||
import org.graalvm.compiler.debug.DebugHandlersFactory;
|
||||
import org.graalvm.compiler.graph.Node;
|
||||
@ -45,7 +46,7 @@ import jdk.vm.ci.code.TargetDescription;
|
||||
import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider;
|
||||
import jdk.vm.ci.meta.MetaAccessProvider;
|
||||
|
||||
public class AArch64HotSpotLoweringProvider extends DefaultHotSpotLoweringProvider {
|
||||
public class AArch64HotSpotLoweringProvider extends DefaultHotSpotLoweringProvider implements AArch64LoweringProviderMixin {
|
||||
|
||||
private AArch64IntegerArithmeticSnippets integerArithmeticSnippets;
|
||||
private AArch64FloatArithmeticSnippets floatArithmeticSnippets;
|
||||
|
@ -27,6 +27,7 @@ package org.graalvm.compiler.hotspot.amd64;
|
||||
import static org.graalvm.compiler.hotspot.HotSpotBackend.Options.GraalArithmeticStubs;
|
||||
|
||||
import org.graalvm.compiler.api.replacements.Snippet;
|
||||
import org.graalvm.compiler.core.amd64.AMD64LoweringProviderMixin;
|
||||
import org.graalvm.compiler.core.common.spi.ForeignCallsProvider;
|
||||
import org.graalvm.compiler.debug.DebugHandlersFactory;
|
||||
import org.graalvm.compiler.graph.Node;
|
||||
@ -53,7 +54,7 @@ import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider;
|
||||
import jdk.vm.ci.meta.MetaAccessProvider;
|
||||
import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||
|
||||
public class AMD64HotSpotLoweringProvider extends DefaultHotSpotLoweringProvider {
|
||||
public class AMD64HotSpotLoweringProvider extends DefaultHotSpotLoweringProvider implements AMD64LoweringProviderMixin {
|
||||
|
||||
private AMD64ConvertSnippets.Templates convertSnippets;
|
||||
private ProbabilisticProfileSnippets.Templates profileSnippets;
|
||||
@ -135,14 +136,4 @@ public class AMD64HotSpotLoweringProvider extends DefaultHotSpotLoweringProvider
|
||||
ForeignCallNode call = graph.add(new ForeignCallNode(foreignCalls, dispatchNode.getStubCallDescriptor(), dispatchNode.getStubCallArgs()));
|
||||
graph.replaceFixed(dispatchNode, call);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer smallestCompareWidth() {
|
||||
return 8;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportBulkZeroing() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
|
||||
|
||||
import jdk.vm.ci.code.Register;
|
||||
import jdk.vm.ci.code.ValueUtil;
|
||||
import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant;
|
||||
import jdk.vm.ci.hotspot.HotSpotConstant;
|
||||
import jdk.vm.ci.meta.Constant;
|
||||
import jdk.vm.ci.meta.Value;
|
||||
|
||||
@ -58,8 +58,8 @@ final class AMD64HotSpotStrategySwitchOp extends AMD64ControlFlow.StrategySwitch
|
||||
|
||||
@Override
|
||||
protected void emitComparison(Constant c) {
|
||||
if (c instanceof HotSpotMetaspaceConstant) {
|
||||
HotSpotMetaspaceConstant meta = (HotSpotMetaspaceConstant) c;
|
||||
if (c instanceof HotSpotConstant) {
|
||||
HotSpotConstant meta = (HotSpotConstant) c;
|
||||
if (meta.isCompressed()) {
|
||||
crb.recordInlineDataInCode(meta);
|
||||
masm.cmpl(keyRegister, 0xDEADDEAD);
|
||||
|
@ -28,6 +28,7 @@ import static org.graalvm.compiler.test.SubprocessUtil.getVMCommandLine;
|
||||
import static org.graalvm.compiler.test.SubprocessUtil.withoutDebuggerArguments;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
@ -100,7 +101,7 @@ public class BenchmarkCounterOverflowTest extends LIRTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void spawnSubprocess() throws Throwable {
|
||||
public void spawnSubprocess() throws IOException, InterruptedException {
|
||||
Assume.assumeFalse("subprocess already spawned -> skip", Boolean.getBoolean(SUBPROCESS_PROPERTY));
|
||||
List<String> vmArgs = withoutDebuggerArguments(getVMCommandLine());
|
||||
vmArgs.add("-XX:JVMCICounterSize=1");
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2019, 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
|
||||
@ -120,7 +120,7 @@ public class ExceedMaxOopMapStackOffset extends LIRTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runStackObjects() throws Throwable {
|
||||
public void runStackObjects() {
|
||||
int max = ((HotSpotBackend) getBackend()).getRuntime().getVMConfig().maxOopMapStackOffset;
|
||||
if (max == Integer.MAX_VALUE) {
|
||||
max = 16 * 1024 - 64;
|
||||
|
@ -153,7 +153,7 @@ public class MitigateExceedingMaxOopMapStackOffsetTest extends LIRTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runStackObjects() throws Throwable {
|
||||
public void runStackObjects() {
|
||||
int max = ((HotSpotBackend) getBackend()).getRuntime().getVMConfig().maxOopMapStackOffset;
|
||||
Assume.assumeFalse("no limit on oop map size", max == Integer.MAX_VALUE);
|
||||
numPrimitiveSlots = (max / 8) * 2;
|
||||
|
@ -25,6 +25,7 @@
|
||||
package org.graalvm.compiler.hotspot.sparc;
|
||||
|
||||
import org.graalvm.compiler.core.common.spi.ForeignCallsProvider;
|
||||
import org.graalvm.compiler.core.sparc.SparcLoweringProviderMixin;
|
||||
import org.graalvm.compiler.graph.Node;
|
||||
import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
|
||||
import org.graalvm.compiler.hotspot.meta.DefaultHotSpotLoweringProvider;
|
||||
@ -36,7 +37,7 @@ import jdk.vm.ci.code.TargetDescription;
|
||||
import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider;
|
||||
import jdk.vm.ci.meta.MetaAccessProvider;
|
||||
|
||||
public class SPARCHotSpotLoweringProvider extends DefaultHotSpotLoweringProvider {
|
||||
public class SPARCHotSpotLoweringProvider extends DefaultHotSpotLoweringProvider implements SparcLoweringProviderMixin {
|
||||
|
||||
public SPARCHotSpotLoweringProvider(HotSpotGraalRuntimeProvider runtime, MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls, HotSpotRegistersProvider registers,
|
||||
HotSpotConstantReflectionProvider constantReflection, TargetDescription target) {
|
||||
|
@ -24,85 +24,97 @@
|
||||
|
||||
package org.graalvm.compiler.hotspot.test;
|
||||
|
||||
import static org.graalvm.compiler.serviceprovider.JavaVersionUtil.JAVA_SPEC;
|
||||
|
||||
import org.graalvm.compiler.api.directives.GraalDirectives;
|
||||
import org.graalvm.compiler.core.test.GraalCompilerTest;
|
||||
import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Assume;
|
||||
import org.junit.Test;
|
||||
|
||||
public class BoxDeoptimizationTest extends GraalCompilerTest {
|
||||
private static boolean isJDK13OrLater = JavaVersionUtil.JAVA_SPEC >= 13;
|
||||
|
||||
public static void testInteger() {
|
||||
Object[] values = {42, new Exception()};
|
||||
private static void checkJDK() {
|
||||
Assume.assumeTrue(JAVA_SPEC == 8 || JAVA_SPEC >= 13);
|
||||
}
|
||||
|
||||
public static void testIntegerSnippet() {
|
||||
Object[] values = {42, -42, new Exception()};
|
||||
GraalDirectives.deoptimize();
|
||||
Assert.assertSame(values[0], Integer.valueOf(42));
|
||||
Assert.assertSame(values[1], Integer.valueOf(-42));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test1() {
|
||||
Assume.assumeTrue(isJDK13OrLater);
|
||||
test("testInteger");
|
||||
public void testInteger() {
|
||||
checkJDK();
|
||||
test("testIntegerSnippet");
|
||||
}
|
||||
|
||||
public static void testLong() {
|
||||
Object[] values = {42L, new Exception()};
|
||||
public static void testLongSnippet() {
|
||||
long highBitsOnly = 2L << 40;
|
||||
Object[] values = {42L, -42L, highBitsOnly, new Exception()};
|
||||
GraalDirectives.deoptimize();
|
||||
Assert.assertSame(values[0], Long.valueOf(42));
|
||||
Assert.assertSame(values[1], Long.valueOf(-42));
|
||||
Assert.assertNotSame(values[2], highBitsOnly);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test2() {
|
||||
Assume.assumeTrue(isJDK13OrLater);
|
||||
test("testLong");
|
||||
public void testLong() {
|
||||
checkJDK();
|
||||
test("testLongSnippet");
|
||||
}
|
||||
|
||||
public static void testChar() {
|
||||
Object[] values = {'a', new Exception()};
|
||||
public static void testCharSnippet() {
|
||||
Object[] values = {'a', 'Z', new Exception()};
|
||||
GraalDirectives.deoptimize();
|
||||
Assert.assertSame(values[0], Character.valueOf('a'));
|
||||
Assert.assertSame(values[1], Character.valueOf('Z'));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test3() {
|
||||
Assume.assumeTrue(isJDK13OrLater);
|
||||
test("testChar");
|
||||
public void testChar() {
|
||||
checkJDK();
|
||||
test("testCharSnippet");
|
||||
}
|
||||
|
||||
public static void testShort() {
|
||||
Object[] values = {(short) 42, new Exception()};
|
||||
public static void testShortSnippet() {
|
||||
Object[] values = {(short) 42, (short) -42, new Exception()};
|
||||
GraalDirectives.deoptimize();
|
||||
Assert.assertSame(values[0], Short.valueOf((short) 42));
|
||||
Assert.assertSame(values[1], Short.valueOf((short) -42));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test4() {
|
||||
Assume.assumeTrue(isJDK13OrLater);
|
||||
test("testShort");
|
||||
public void testShort() {
|
||||
checkJDK();
|
||||
test("testShortSnippet");
|
||||
}
|
||||
|
||||
public static void testByte() {
|
||||
Object[] values = {(byte) 42, new Exception()};
|
||||
public static void testByteSnippet() {
|
||||
Object[] values = {(byte) 42, (byte) -42, new Exception()};
|
||||
GraalDirectives.deoptimize();
|
||||
Assert.assertSame(values[0], Byte.valueOf((byte) 42));
|
||||
Assert.assertSame(values[1], Byte.valueOf((byte) -42));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test5() {
|
||||
Assume.assumeTrue(isJDK13OrLater);
|
||||
test("testByte");
|
||||
public void testByte() {
|
||||
checkJDK();
|
||||
test("testByteSnippet");
|
||||
}
|
||||
|
||||
public static void testBoolean() {
|
||||
Object[] values = {true, new Exception()};
|
||||
public static void testBooleanSnippet() {
|
||||
Object[] values = {true, false, new Exception()};
|
||||
GraalDirectives.deoptimize();
|
||||
Assert.assertSame(values[0], Boolean.valueOf(true));
|
||||
Assert.assertSame(values[1], Boolean.valueOf(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test6() {
|
||||
Assume.assumeTrue(isJDK13OrLater);
|
||||
test("testBoolean");
|
||||
public void testBoolean() {
|
||||
checkJDK();
|
||||
test("testBooleanSnippet");
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,9 @@
|
||||
|
||||
package org.graalvm.compiler.hotspot.test;
|
||||
|
||||
import static org.graalvm.compiler.hotspot.meta.HotSpotGraphBuilderPlugins.aesDecryptName;
|
||||
import static org.graalvm.compiler.hotspot.meta.HotSpotGraphBuilderPlugins.aesEncryptName;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@ -41,6 +44,7 @@ import jdk.internal.vm.compiler.collections.MapCursor;
|
||||
import org.graalvm.compiler.api.test.Graal;
|
||||
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
|
||||
import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
|
||||
import org.graalvm.compiler.hotspot.meta.HotSpotGraphBuilderPlugins;
|
||||
import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
|
||||
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
|
||||
import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin;
|
||||
@ -501,21 +505,17 @@ public class CheckGraalIntrinsics extends GraalTest {
|
||||
"java/util/zip/CRC32C.updateDirectByteBuffer(IJII)I");
|
||||
}
|
||||
|
||||
boolean implNames = HotSpotGraphBuilderPlugins.cbcUsesImplNames(config);
|
||||
String cbcEncryptName = implNames ? "implEncrypt" : "encrypt";
|
||||
String cbcDecryptName = implNames ? "implDecrypt" : "decrypt";
|
||||
|
||||
// AES intrinsics
|
||||
if (!config.useAESIntrinsics) {
|
||||
if (isJDK9OrHigher()) {
|
||||
add(ignore,
|
||||
"com/sun/crypto/provider/AESCrypt.implDecryptBlock([BI[BI)V",
|
||||
"com/sun/crypto/provider/AESCrypt.implEncryptBlock([BI[BI)V",
|
||||
"com/sun/crypto/provider/CipherBlockChaining.implDecrypt([BII[BI)I",
|
||||
"com/sun/crypto/provider/CipherBlockChaining.implEncrypt([BII[BI)I");
|
||||
} else {
|
||||
add(ignore,
|
||||
"com/sun/crypto/provider/AESCrypt.decryptBlock([BI[BI)V",
|
||||
"com/sun/crypto/provider/AESCrypt.encryptBlock([BI[BI)V",
|
||||
"com/sun/crypto/provider/CipherBlockChaining.decrypt([BII[BI)I",
|
||||
"com/sun/crypto/provider/CipherBlockChaining.encrypt([BII[BI)I");
|
||||
}
|
||||
add(ignore,
|
||||
"com/sun/crypto/provider/AESCrypt." + aesDecryptName + "([BI[BI)V",
|
||||
"com/sun/crypto/provider/AESCrypt." + aesEncryptName + "([BI[BI)V",
|
||||
"com/sun/crypto/provider/CipherBlockChaining." + cbcDecryptName + "([BII[BI)I",
|
||||
"com/sun/crypto/provider/CipherBlockChaining." + cbcEncryptName + "([BII[BI)I");
|
||||
}
|
||||
|
||||
// BigInteger intrinsics
|
||||
|
@ -29,6 +29,7 @@ import static org.graalvm.compiler.test.SubprocessUtil.withoutDebuggerArguments;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
@ -209,10 +210,9 @@ public class CompilationWrapperTest extends GraalCompilerTest {
|
||||
System.out.println(proc);
|
||||
}
|
||||
|
||||
List<Probe> probes = new ArrayList<>(initialProbes);
|
||||
Probe diagnosticProbe = null;
|
||||
if (!extraVmArgs.contains("-Dgraal.TruffleCompilationExceptionsAreFatal=true")) {
|
||||
diagnosticProbe = new Probe("Graal diagnostic output saved in ", 1);
|
||||
try {
|
||||
List<Probe> probes = new ArrayList<>(initialProbes);
|
||||
Probe diagnosticProbe = new Probe("Graal diagnostic output saved in ", 1);
|
||||
probes.add(diagnosticProbe);
|
||||
probes.add(new Probe("Forced crash after compiling", Integer.MAX_VALUE) {
|
||||
@Override
|
||||
@ -220,22 +220,20 @@ public class CompilationWrapperTest extends GraalCompilerTest {
|
||||
return actualOccurrences > 0 ? null : "expected at least 1 occurrence";
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
for (String line : proc.output) {
|
||||
for (Probe probe : probes) {
|
||||
if (probe.matches(line)) {
|
||||
break;
|
||||
for (String line : proc.output) {
|
||||
for (Probe probe : probes) {
|
||||
if (probe.matches(line)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (Probe probe : probes) {
|
||||
String error = probe.test();
|
||||
if (error != null) {
|
||||
Assert.fail(String.format("Did not find expected occurences of '%s' in output of command: %s%n%s", probe.substring, error, proc));
|
||||
for (Probe probe : probes) {
|
||||
String error = probe.test();
|
||||
if (error != null) {
|
||||
Assert.fail(String.format("Did not find expected occurences of '%s' in output of command: %s%n%s", probe.substring, error, proc));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (diagnosticProbe != null) {
|
||||
String line = diagnosticProbe.lastMatchingLine;
|
||||
int substringStart = line.indexOf(diagnosticProbe.substring);
|
||||
int substringLength = diagnosticProbe.substring.length();
|
||||
@ -263,8 +261,10 @@ public class CompilationWrapperTest extends GraalCompilerTest {
|
||||
}
|
||||
} finally {
|
||||
zip.delete();
|
||||
dumpPath.delete();
|
||||
}
|
||||
} finally {
|
||||
Path directory = dumpPath.toPath();
|
||||
removeDirectory(directory);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -313,8 +313,8 @@ public class CompressedOopTest extends GraalCompilerTest {
|
||||
Assert.assertTrue(buffer.length() == 28);
|
||||
String a = new String("TestTestTestTestTestTestTest");
|
||||
installedBenchmarkCode.executeVarargs(buffer, a.toCharArray());
|
||||
Assert.assertTrue(buffer.length() == 56);
|
||||
Assert.assertTrue(buffer.toString().equals("TestTestTestTestTestTestTestTestTestTestTestTestTestTest"));
|
||||
Assert.assertEquals(56, buffer.length());
|
||||
Assert.assertEquals("TestTestTestTestTestTestTestTestTestTestTestTestTestTest", buffer.toString());
|
||||
}
|
||||
|
||||
public static void stringBuilderTest(Object c1, Object c2) {
|
||||
@ -339,8 +339,8 @@ public class CompressedOopTest extends GraalCompilerTest {
|
||||
for (int i = 0; i < add.length; i++) {
|
||||
buffer.append(add[i]);
|
||||
}
|
||||
Assert.assertTrue(buffer.length() == 56);
|
||||
Assert.assertTrue(buffer.toString().equals("TestTestTestTestTestTestTestTestTestTestTestTestTestTest"));
|
||||
Assert.assertEquals(56, buffer.length());
|
||||
Assert.assertEquals("TestTestTestTestTestTestTestTestTestTestTestTestTestTest", buffer.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -356,8 +356,8 @@ public class CompressedOopTest extends GraalCompilerTest {
|
||||
char[] dst = new char[buffer.length() * 2];
|
||||
System.arraycopy(buffer.toString().toCharArray(), 0, dst, 0, buffer.length());
|
||||
System.arraycopy(a.toCharArray(), 0, dst, buffer.length(), buffer.length());
|
||||
Assert.assertTrue(dst.length == 56);
|
||||
Assert.assertTrue(new String(dst).equals("TestTestTestTestTestTestTestTestTestTestTestTestTestTest"));
|
||||
Assert.assertEquals(56, dst.length);
|
||||
Assert.assertEquals("TestTestTestTestTestTestTestTestTestTestTestTestTestTest", new String(dst));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -35,12 +35,11 @@ import javax.crypto.Cipher;
|
||||
import javax.crypto.KeyGenerator;
|
||||
import javax.crypto.SecretKey;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.graalvm.compiler.code.CompilationResult;
|
||||
import org.graalvm.compiler.debug.DebugContext;
|
||||
import org.graalvm.compiler.hotspot.meta.HotSpotGraphBuilderPlugins;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import jdk.vm.ci.code.InstalledCode;
|
||||
import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||
@ -91,7 +90,10 @@ public class HotSpotCryptoSubstitutionTest extends HotSpotGraalCompilerTest {
|
||||
|
||||
@Test
|
||||
public void testCipherBlockChainingIntrinsics() throws Exception {
|
||||
if (compileAndInstall("com.sun.crypto.provider.CipherBlockChaining", HotSpotGraphBuilderPlugins.cbcEncryptName, HotSpotGraphBuilderPlugins.cbcDecryptName)) {
|
||||
boolean implNames = HotSpotGraphBuilderPlugins.cbcUsesImplNames(runtime().getVMConfig());
|
||||
String cbcEncryptName = implNames ? "implEncrypt" : "encrypt";
|
||||
String cbcDecryptName = implNames ? "implDecrypt" : "decrypt";
|
||||
if (compileAndInstall("com.sun.crypto.provider.CipherBlockChaining", cbcEncryptName, cbcDecryptName)) {
|
||||
ByteArrayOutputStream actual = new ByteArrayOutputStream();
|
||||
actual.write(runEncryptDecrypt(aesKey, "AES/CBC/NoPadding"));
|
||||
actual.write(runEncryptDecrypt(aesKey, "AES/CBC/PKCS5Padding"));
|
||||
|
@ -378,12 +378,15 @@ public class HotSpotGraalManagementTest {
|
||||
MBeanAttributeInfo dumpPath = findAttributeInfo("DumpPath", info);
|
||||
MBeanAttributeInfo printGraphFile = findAttributeInfo("PrintGraphFile", info);
|
||||
MBeanAttributeInfo showDumpFiles = findAttributeInfo("ShowDumpFiles", info);
|
||||
MBeanAttributeInfo methodFilter = findAttributeInfo("MethodFilter", info);
|
||||
Object originalDumpPath = server.getAttribute(mbeanName, dumpPath.getName());
|
||||
Object originalPrintGraphFile = server.getAttribute(mbeanName, printGraphFile.getName());
|
||||
Object originalShowDumpFiles = server.getAttribute(mbeanName, showDumpFiles.getName());
|
||||
Object originalMethodFilter = server.getAttribute(mbeanName, methodFilter.getName());
|
||||
final File tmpDir = new File(HotSpotGraalManagementTest.class.getSimpleName() + "_" + System.currentTimeMillis()).getAbsoluteFile();
|
||||
|
||||
server.setAttribute(mbeanName, new Attribute(dumpPath.getName(), quoted(tmpDir)));
|
||||
server.setAttribute(mbeanName, new Attribute(methodFilter.getName(), ""));
|
||||
// Force output to a file even if there's a running IGV instance available.
|
||||
server.setAttribute(mbeanName, new Attribute(printGraphFile.getName(), true));
|
||||
server.setAttribute(mbeanName, new Attribute(showDumpFiles.getName(), false));
|
||||
@ -392,6 +395,7 @@ public class HotSpotGraalManagementTest {
|
||||
server.invoke(mbeanName, "dumpMethod", params, null);
|
||||
boolean found = false;
|
||||
String expectedIgvDumpSuffix = "[Arrays.asList(Object[])List].bgv";
|
||||
Assert.assertTrue(tmpDir.toString() + " was not created or is not a directory", tmpDir.isDirectory());
|
||||
List<String> dumpPathEntries = Arrays.asList(tmpDir.list());
|
||||
for (String entry : dumpPathEntries) {
|
||||
if (entry.endsWith(expectedIgvDumpSuffix)) {
|
||||
@ -403,8 +407,11 @@ public class HotSpotGraalManagementTest {
|
||||
dumpPathEntries.stream().collect(Collectors.joining(System.lineSeparator()))));
|
||||
}
|
||||
} finally {
|
||||
deleteDirectory(tmpDir.toPath());
|
||||
if (tmpDir.isDirectory()) {
|
||||
deleteDirectory(tmpDir.toPath());
|
||||
}
|
||||
server.setAttribute(mbeanName, new Attribute(dumpPath.getName(), originalDumpPath));
|
||||
server.setAttribute(mbeanName, new Attribute(methodFilter.getName(), originalMethodFilter));
|
||||
server.setAttribute(mbeanName, new Attribute(printGraphFile.getName(), originalPrintGraphFile));
|
||||
server.setAttribute(mbeanName, new Attribute(showDumpFiles.getName(), originalShowDumpFiles));
|
||||
}
|
||||
|
@ -27,9 +27,13 @@ package org.graalvm.compiler.hotspot.test;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Random;
|
||||
|
||||
import org.graalvm.compiler.core.test.GraalCompilerTest;
|
||||
import org.graalvm.compiler.hotspot.JVMCIVersionCheck;
|
||||
import org.graalvm.compiler.hotspot.JVMCIVersionCheck.Version;
|
||||
import org.graalvm.compiler.hotspot.JVMCIVersionCheck.Version2;
|
||||
import org.graalvm.compiler.hotspot.JVMCIVersionCheck.Version3;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
@ -43,24 +47,37 @@ public class JVMCIVersionCheckTest extends GraalCompilerTest {
|
||||
props.put(name, sprops.getProperty(name));
|
||||
}
|
||||
|
||||
for (int i = 0; i < 100; i++) {
|
||||
int minMajor = i;
|
||||
int minMinor = 100 - i;
|
||||
for (int j = 0; j < 100; j++) {
|
||||
int major = j;
|
||||
int minor = 100 - j;
|
||||
long seed = Long.getLong("test.seed", System.nanoTime());
|
||||
Random random = new Random(seed);
|
||||
|
||||
boolean ok = (major > minMajor) || (major == minMajor && minor >= minMinor);
|
||||
for (String sep : new String[]{".", "-b"}) {
|
||||
String javaVmVersion = String.format("prefix-jvmci-%03d%s%03d-suffix", major, sep, minor);
|
||||
if (ok) {
|
||||
JVMCIVersionCheck.check(props, minMajor, minMinor, "1.8", javaVmVersion, false);
|
||||
} else {
|
||||
try {
|
||||
JVMCIVersionCheck.check(props, minMajor, minMinor, "1.8", javaVmVersion, false);
|
||||
Assert.fail("expected to fail checking " + javaVmVersion + " against " + minMajor + "." + minMinor);
|
||||
} catch (InternalError e) {
|
||||
// pass
|
||||
for (int i = 0; i < 50; i++) {
|
||||
int minMajor = i;
|
||||
int minMinor = 50 - i;
|
||||
for (int j = 0; j < 50; j++) {
|
||||
int major = j;
|
||||
int minor = 50 - j;
|
||||
|
||||
for (int k = 0; k < 30; k++) {
|
||||
int minBuild = random.nextInt(100);
|
||||
int build = random.nextInt(100);
|
||||
|
||||
for (Version version : new Version[]{new Version2(major, minor), new Version3(major, minor, build)}) {
|
||||
for (Version minVersion : new Version[]{new Version2(minMajor, minMinor), new Version3(minMajor, minMinor, minBuild)}) {
|
||||
String javaVmVersion = String.format("prefix-jvmci-%s-suffix", version);
|
||||
if (!version.isLessThan(minVersion)) {
|
||||
try {
|
||||
JVMCIVersionCheck.check(props, minVersion, "1.8", javaVmVersion, false);
|
||||
} catch (InternalError e) {
|
||||
throw new AssertionError("Failed " + JVMCIVersionCheckTest.class.getSimpleName() + " with -Dtest.seed=" + seed, e);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
JVMCIVersionCheck.check(props, minVersion, "1.8", javaVmVersion, false);
|
||||
Assert.fail("expected to fail checking " + javaVmVersion + " against " + minVersion + " (-Dtest.seed=" + seed + ")");
|
||||
} catch (InternalError e) {
|
||||
// pass
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -72,8 +89,9 @@ public class JVMCIVersionCheckTest extends GraalCompilerTest {
|
||||
for (String version : new String[]{"0" + sep + Long.MAX_VALUE, Long.MAX_VALUE + sep + 0}) {
|
||||
String javaVmVersion = String.format("prefix-jvmci-%s-suffix", version);
|
||||
try {
|
||||
JVMCIVersionCheck.check(props, 0, 59, "1.8", javaVmVersion, false);
|
||||
Assert.fail("expected to fail checking " + javaVmVersion + " against 0.59");
|
||||
Version2 minVersion = new Version2(0, 59);
|
||||
JVMCIVersionCheck.check(props, minVersion, "1.8", javaVmVersion, false);
|
||||
Assert.fail("expected to fail checking " + javaVmVersion + " against " + minVersion);
|
||||
} catch (InternalError e) {
|
||||
// pass
|
||||
}
|
||||
|
@ -234,4 +234,3 @@ public class NodeCostDumpUtil {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
69
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationContext.java
Normal file
69
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationContext.java
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 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;
|
||||
|
||||
import org.graalvm.compiler.debug.GraalError;
|
||||
|
||||
import jdk.vm.ci.meta.JavaConstant;
|
||||
|
||||
/**
|
||||
* A context for scoping the lifetime of foreign objects.
|
||||
*
|
||||
* The need for this mechanism is best explained with an example. When folding a GETFIELD bytecode
|
||||
* denoting a {@code final static} non-primitive field, libgraal can create a {@link JavaConstant}
|
||||
* wrapping a handle to the field's value in the HotSpot heap. This handle must be released before
|
||||
* HotSpot can reclaim the object it references. Performing a compilation in the scope of a
|
||||
* {@linkplain HotSpotGraalServices#openLocalCompilationContext local} context ensures the handle is
|
||||
* released once the compilation completes, allowing the HotSpot GC to subsequently reclaim the
|
||||
* HotSpot object. When libgraal creates data structures that outlive a single compilation and may
|
||||
* contain foreign object references (e.g. snippet graphs), it must enter the
|
||||
* {@linkplain HotSpotGraalServices#enterGlobalCompilationContext global} context. Foreign object
|
||||
* handles created in the global context are only released once their {@link JavaConstant} wrappers
|
||||
* are reclaimed by the libgraal GC.
|
||||
*
|
||||
* {@link CompilationContext}s have no impact on {@link JavaConstant}s that do not encapsulate a
|
||||
* foreign object reference.
|
||||
*
|
||||
* The object returned by {@link HotSpotGraalServices#enterGlobalCompilationContext} or
|
||||
* {@link HotSpotGraalServices#openLocalCompilationContext} should be used in a try-with-resources
|
||||
* statement. Failure to close a context will almost certainly result in foreign objects being
|
||||
* leaked.
|
||||
*/
|
||||
public class CompilationContext implements AutoCloseable {
|
||||
private final AutoCloseable impl;
|
||||
|
||||
CompilationContext(AutoCloseable impl) {
|
||||
this.impl = impl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
try {
|
||||
impl.close();
|
||||
} catch (Exception e) {
|
||||
GraalError.shouldNotReachHere(e);
|
||||
}
|
||||
}
|
||||
}
|
@ -26,6 +26,7 @@ package org.graalvm.compiler.hotspot;
|
||||
|
||||
import static org.graalvm.compiler.hotspot.HotSpotGraalCompiler.fmt;
|
||||
import static org.graalvm.compiler.hotspot.HotSpotGraalCompiler.str;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
@ -35,9 +36,10 @@ import java.util.TreeSet;
|
||||
|
||||
import org.graalvm.compiler.debug.TTY;
|
||||
import org.graalvm.compiler.options.Option;
|
||||
import org.graalvm.compiler.options.OptionKey;
|
||||
import org.graalvm.compiler.options.OptionType;
|
||||
import org.graalvm.compiler.options.OptionValues;
|
||||
import org.graalvm.compiler.options.OptionKey;
|
||||
|
||||
import jdk.vm.ci.code.CompilationRequest;
|
||||
import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||
|
||||
@ -85,7 +87,7 @@ class CompilationCounters {
|
||||
}
|
||||
}
|
||||
TTY.flush();
|
||||
System.exit(-1);
|
||||
HotSpotGraalServices.exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -96,9 +96,14 @@ public class CompilationTask {
|
||||
return DebugContext.create(retryOptions, description, initialDebug.getGlobalMetrics(), logStream, factories);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void exitHostVM(int status) {
|
||||
HotSpotGraalServices.exit(status);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getMethod().format("%H.%n(%p)");
|
||||
return getMethod().format("%H.%n(%p) @ " + getEntryBCI());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -238,7 +238,7 @@ class CompilationWatchDog implements Runnable, AutoCloseable {
|
||||
TTY.printf("======================= WATCH DOG THREAD =======================%n" +
|
||||
"%s took %d identical stack traces, which indicates a stuck compilation (id=%d) of %s%n%sExiting VM%n", this,
|
||||
numberOfIdenticalStackTraces, currentId, fmt(currentMethod), fmt(lastStackTrace));
|
||||
System.exit(-1);
|
||||
HotSpotGraalServices.exit(-1);
|
||||
}
|
||||
} else if (newStackTrace) {
|
||||
synchronized (CompilationWatchDog.class) {
|
||||
|
@ -200,7 +200,7 @@ public abstract class CompilerConfigurationFactory implements Comparable<Compile
|
||||
for (CompilerConfigurationFactory candidate : getAllCandidates()) {
|
||||
System.out.println(" " + candidate.name);
|
||||
}
|
||||
System.exit(0);
|
||||
HotSpotGraalServices.exit(0);
|
||||
} else if (value != null) {
|
||||
for (CompilerConfigurationFactory candidate : GraalServices.load(CompilerConfigurationFactory.class)) {
|
||||
if (candidate.name.equals(value)) {
|
||||
|
@ -111,39 +111,41 @@ public class HotSpotGraalCompiler implements GraalJVMCICompiler, Cancellable {
|
||||
|
||||
@SuppressWarnings("try")
|
||||
CompilationRequestResult compileMethod(CompilationRequest request, boolean installAsDefault, OptionValues initialOptions) {
|
||||
if (graalRuntime.isShutdown()) {
|
||||
return HotSpotCompilationRequestResult.failure(String.format("Shutdown entered"), true);
|
||||
}
|
||||
|
||||
ResolvedJavaMethod method = request.getMethod();
|
||||
|
||||
if (graalRuntime.isBootstrapping()) {
|
||||
if (DebugOptions.BootstrapInitializeOnly.getValue(initialOptions)) {
|
||||
return HotSpotCompilationRequestResult.failure(String.format("Skip compilation because %s is enabled", DebugOptions.BootstrapInitializeOnly.getName()), true);
|
||||
try (CompilationContext scope = HotSpotGraalServices.openLocalCompilationContext(request)) {
|
||||
if (graalRuntime.isShutdown()) {
|
||||
return HotSpotCompilationRequestResult.failure(String.format("Shutdown entered"), true);
|
||||
}
|
||||
if (bootstrapWatchDog != null) {
|
||||
if (bootstrapWatchDog.hitCriticalCompilationRateOrTimeout()) {
|
||||
// Drain the compilation queue to expedite completion of the bootstrap
|
||||
return HotSpotCompilationRequestResult.failure("hit critical bootstrap compilation rate or timeout", true);
|
||||
|
||||
ResolvedJavaMethod method = request.getMethod();
|
||||
|
||||
if (graalRuntime.isBootstrapping()) {
|
||||
if (DebugOptions.BootstrapInitializeOnly.getValue(initialOptions)) {
|
||||
return HotSpotCompilationRequestResult.failure(String.format("Skip compilation because %s is enabled", DebugOptions.BootstrapInitializeOnly.getName()), true);
|
||||
}
|
||||
if (bootstrapWatchDog != null) {
|
||||
if (bootstrapWatchDog.hitCriticalCompilationRateOrTimeout()) {
|
||||
// Drain the compilation queue to expedite completion of the bootstrap
|
||||
return HotSpotCompilationRequestResult.failure("hit critical bootstrap compilation rate or timeout", true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
HotSpotCompilationRequest hsRequest = (HotSpotCompilationRequest) request;
|
||||
CompilationTask task = new CompilationTask(jvmciRuntime, this, hsRequest, true, shouldRetainLocalVariables(hsRequest.getJvmciEnv()), installAsDefault);
|
||||
OptionValues options = task.filterOptions(initialOptions);
|
||||
try (CompilationWatchDog w1 = CompilationWatchDog.watch(method, hsRequest.getId(), options);
|
||||
BootstrapWatchDog.Watch w2 = bootstrapWatchDog == null ? null : bootstrapWatchDog.watch(request);
|
||||
CompilationAlarm alarm = CompilationAlarm.trackCompilationPeriod(options);) {
|
||||
if (compilationCounters != null) {
|
||||
compilationCounters.countCompilation(method);
|
||||
HotSpotCompilationRequest hsRequest = (HotSpotCompilationRequest) request;
|
||||
CompilationTask task = new CompilationTask(jvmciRuntime, this, hsRequest, true, shouldRetainLocalVariables(hsRequest.getJvmciEnv()), installAsDefault);
|
||||
OptionValues options = task.filterOptions(initialOptions);
|
||||
try (CompilationWatchDog w1 = CompilationWatchDog.watch(method, hsRequest.getId(), options);
|
||||
BootstrapWatchDog.Watch w2 = bootstrapWatchDog == null ? null : bootstrapWatchDog.watch(request);
|
||||
CompilationAlarm alarm = CompilationAlarm.trackCompilationPeriod(options);) {
|
||||
if (compilationCounters != null) {
|
||||
compilationCounters.countCompilation(method);
|
||||
}
|
||||
CompilationRequestResult r = null;
|
||||
try (DebugContext debug = graalRuntime.openDebugContext(options, task.getCompilationIdentifier(), method, getDebugHandlersFactories(), DebugContext.DEFAULT_LOG_STREAM);
|
||||
Activation a = debug.activate()) {
|
||||
r = task.runCompilation(debug);
|
||||
}
|
||||
assert r != null;
|
||||
return r;
|
||||
}
|
||||
CompilationRequestResult r = null;
|
||||
try (DebugContext debug = graalRuntime.openDebugContext(options, task.getCompilationIdentifier(), method, getDebugHandlersFactories(), DebugContext.DEFAULT_LOG_STREAM);
|
||||
Activation a = debug.activate()) {
|
||||
r = task.runCompilation(debug);
|
||||
}
|
||||
assert r != null;
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,9 @@ package org.graalvm.compiler.hotspot;
|
||||
|
||||
import jdk.vm.ci.hotspot.HotSpotMetaData;
|
||||
|
||||
/**
|
||||
* JDK 13 version of {@code HotSpotGraalServices}.
|
||||
*/
|
||||
public class HotSpotGraalServices {
|
||||
|
||||
/**
|
||||
@ -35,4 +38,17 @@ public class HotSpotGraalServices {
|
||||
public static byte[] getImplicitExceptionBytes(HotSpotMetaData metaData) {
|
||||
return metaData.implicitExceptionBytes();
|
||||
}
|
||||
|
||||
public static CompilationContext enterGlobalCompilationContext() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public static CompilationContext openLocalCompilationContext(Object description) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void exit(int status) {
|
||||
System.exit(status);
|
||||
}
|
||||
}
|
||||
|
@ -208,6 +208,7 @@ public class HotSpotReplacementsImpl extends ReplacementsImpl {
|
||||
return super.getSnippet(method, recursiveEntry, args, trackNodeSourcePosition, replaceePosition, options);
|
||||
}
|
||||
|
||||
@SuppressWarnings("try")
|
||||
private StructuredGraph getEncodedSnippet(ResolvedJavaMethod method, Object[] args, StructuredGraph.AllowAssumptions allowAssumptions, OptionValues options) {
|
||||
boolean useEncodedGraphs = UseEncodedGraphs.getValue(options);
|
||||
if (IS_IN_NATIVE_IMAGE || useEncodedGraphs) {
|
||||
@ -219,11 +220,15 @@ public class HotSpotReplacementsImpl extends ReplacementsImpl {
|
||||
if (getEncodedSnippets() == null) {
|
||||
throw GraalError.shouldNotReachHere("encoded snippets not found");
|
||||
}
|
||||
StructuredGraph graph = getEncodedSnippets().getEncodedSnippet(method, this, args, allowAssumptions, options);
|
||||
if (graph == null) {
|
||||
throw GraalError.shouldNotReachHere("snippet not found: " + method.format("%H.%n(%p)"));
|
||||
// Snippets graphs can contain foreign object reference and
|
||||
// outlive a single compilation.
|
||||
try (CompilationContext scope = HotSpotGraalServices.enterGlobalCompilationContext()) {
|
||||
StructuredGraph graph = getEncodedSnippets().getEncodedSnippet(method, this, args, allowAssumptions, options);
|
||||
if (graph == null) {
|
||||
throw GraalError.shouldNotReachHere("snippet not found: " + method.format("%H.%n(%p)"));
|
||||
}
|
||||
return graph;
|
||||
}
|
||||
return graph;
|
||||
}
|
||||
} else {
|
||||
assert registeredSnippets == null || registeredSnippets.contains(method) : "Asking for snippet method that was never registered: " + method.format("%H.%n(%p)");
|
||||
|
@ -42,6 +42,7 @@ import org.graalvm.compiler.options.OptionType;
|
||||
import org.graalvm.compiler.serviceprovider.GraalServices;
|
||||
import org.graalvm.compiler.serviceprovider.ServiceProvider;
|
||||
|
||||
import jdk.vm.ci.common.NativeImageReinitialize;
|
||||
import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
|
||||
import jdk.vm.ci.services.Services;
|
||||
|
||||
@ -96,7 +97,7 @@ public class HotSpotTTYStreamProvider implements TTYStreamProvider {
|
||||
* initialization.
|
||||
*/
|
||||
class DelayedOutputStream extends OutputStream {
|
||||
private volatile OutputStream lazy;
|
||||
@NativeImageReinitialize private volatile OutputStream lazy;
|
||||
|
||||
private OutputStream lazy() {
|
||||
if (lazy == null) {
|
||||
|
@ -43,4 +43,3 @@ abstract class IsGraalPredicateBase {
|
||||
return HotSpotJVMCICompilerFactory.CompilationLevelAdjustment.ByHolder;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -28,6 +28,8 @@ import java.util.Formatter;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Mechanism for checking that the current Java runtime environment supports the minimum JVMCI API
|
||||
@ -41,8 +43,107 @@ import java.util.Properties;
|
||||
*/
|
||||
public final class JVMCIVersionCheck {
|
||||
|
||||
private static final int JVMCI8_MIN_MAJOR_VERSION = 19;
|
||||
private static final int JVMCI8_MIN_MINOR_VERSION = 1;
|
||||
private static final Version JVMCI8_MIN_VERSION = new Version3(19, 2, 1);
|
||||
|
||||
public interface Version {
|
||||
boolean isLessThan(Version other);
|
||||
|
||||
static Version parse(String vmVersion) {
|
||||
Matcher m = Pattern.compile(".*-jvmci-(\\d+)\\.(\\d+)-b(\\d+).*").matcher(vmVersion);
|
||||
if (m.matches()) {
|
||||
try {
|
||||
int major = Integer.parseInt(m.group(1));
|
||||
int minor = Integer.parseInt(m.group(2));
|
||||
int build = Integer.parseInt(m.group(3));
|
||||
return new Version3(major, minor, build);
|
||||
} catch (NumberFormatException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
m = Pattern.compile(".*-jvmci-(\\d+)(?:\\.|-b)(\\d+).*").matcher(vmVersion);
|
||||
if (m.matches()) {
|
||||
try {
|
||||
int major = Integer.parseInt(m.group(1));
|
||||
int minor = Integer.parseInt(m.group(2));
|
||||
return new Version2(major, minor);
|
||||
} catch (NumberFormatException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Version2 implements Version {
|
||||
private final int major;
|
||||
private final int minor;
|
||||
|
||||
public Version2(int major, int minor) {
|
||||
this.major = major;
|
||||
this.minor = minor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLessThan(Version other) {
|
||||
if (other.getClass() == Version3.class) {
|
||||
return true;
|
||||
}
|
||||
Version2 o = (Version2) other;
|
||||
if (this.major < o.major) {
|
||||
return true;
|
||||
}
|
||||
if (this.major == o.major && this.minor < o.minor) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (major >= 19) {
|
||||
return String.format("%d-b%02d", major, minor);
|
||||
} else {
|
||||
return String.format("%d.%d", major, minor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class Version3 implements Version {
|
||||
private final int major;
|
||||
private final int minor;
|
||||
private final int build;
|
||||
|
||||
public Version3(int major, int minor, int build) {
|
||||
this.major = major;
|
||||
this.minor = minor;
|
||||
this.build = build;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLessThan(Version other) {
|
||||
if (other.getClass() == Version2.class) {
|
||||
return false;
|
||||
}
|
||||
Version3 o = (Version3) other;
|
||||
if (this.major < o.major) {
|
||||
return true;
|
||||
}
|
||||
if (this.major == o.major) {
|
||||
if (this.minor < o.minor) {
|
||||
return true;
|
||||
}
|
||||
if (this.minor == o.minor && this.build < o.build) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%d.%d-b%02d", major, minor, build);
|
||||
}
|
||||
}
|
||||
|
||||
private static void failVersionCheck(Map<String, String> props, boolean exit, String reason, Object... args) {
|
||||
Formatter errorMessage = new Formatter().format(reason, args);
|
||||
@ -53,9 +154,7 @@ public final class JVMCIVersionCheck {
|
||||
errorMessage.format("Currently used Java home directory is %s.%n", javaHome);
|
||||
errorMessage.format("Currently used VM configuration is: %s%n", vmName);
|
||||
if (props.get("java.specification.version").compareTo("1.9") < 0) {
|
||||
errorMessage.format("Download the latest JVMCI JDK 8 from " +
|
||||
"https://www.oracle.com/technetwork/graalvm/downloads/index.html or " +
|
||||
"https://github.com/graalvm/openjdk8-jvmci-builder/releases");
|
||||
errorMessage.format("Download the latest JVMCI JDK 8 from https://github.com/graalvm/openjdk8-jvmci-builder/releases");
|
||||
} else {
|
||||
errorMessage.format("Download JDK 11 or later.");
|
||||
}
|
||||
@ -74,7 +173,6 @@ public final class JVMCIVersionCheck {
|
||||
|
||||
private final String javaSpecVersion;
|
||||
private final String vmVersion;
|
||||
private int cursor;
|
||||
private final Map<String, String> props;
|
||||
|
||||
private JVMCIVersionCheck(Map<String, String> props, String javaSpecVersion, String vmVersion) {
|
||||
@ -85,112 +183,28 @@ public final class JVMCIVersionCheck {
|
||||
|
||||
static void check(Map<String, String> props, boolean exitOnFailure) {
|
||||
JVMCIVersionCheck checker = new JVMCIVersionCheck(props, props.get("java.specification.version"), props.get("java.vm.version"));
|
||||
checker.run(exitOnFailure, JVMCI8_MIN_MAJOR_VERSION, JVMCI8_MIN_MINOR_VERSION);
|
||||
checker.run(exitOnFailure, JVMCI8_MIN_VERSION);
|
||||
}
|
||||
|
||||
/**
|
||||
* Entry point for testing.
|
||||
*/
|
||||
public static void check(Map<String, String> props,
|
||||
int jvmci8MinMajorVersion,
|
||||
int jvmci8MinMinorVersion,
|
||||
Version minVersion,
|
||||
String javaSpecVersion,
|
||||
String javaVmVersion,
|
||||
boolean exitOnFailure) {
|
||||
String javaVmVersion, boolean exitOnFailure) {
|
||||
JVMCIVersionCheck checker = new JVMCIVersionCheck(props, javaSpecVersion, javaVmVersion);
|
||||
checker.run(exitOnFailure, jvmci8MinMajorVersion, jvmci8MinMinorVersion);
|
||||
checker.run(exitOnFailure, minVersion);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a positive decimal number at {@link #cursor}.
|
||||
*
|
||||
* @return -1 if there is no positive decimal number at {@link #cursor}
|
||||
*/
|
||||
private int parseNumber() {
|
||||
int result = -1;
|
||||
while (cursor < vmVersion.length()) {
|
||||
int digit = vmVersion.charAt(cursor) - '0';
|
||||
if (digit >= 0 && digit <= 9) {
|
||||
if (result == -1) {
|
||||
result = digit;
|
||||
} else {
|
||||
long r = (long) result * (long) 10;
|
||||
if ((int) r != r) {
|
||||
// Overflow
|
||||
return -1;
|
||||
}
|
||||
result = (int) r + digit;
|
||||
}
|
||||
cursor++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse {@code "."} or {@code "-b"} at {@link #cursor}.
|
||||
*
|
||||
* @return {@code true} iff there was an expected separator at {@link #cursor}
|
||||
*/
|
||||
private boolean parseSeparator() {
|
||||
if (cursor < vmVersion.length()) {
|
||||
char ch = vmVersion.charAt(cursor);
|
||||
if (ch == '.') {
|
||||
cursor++;
|
||||
return true;
|
||||
}
|
||||
if (ch == '-') {
|
||||
cursor++;
|
||||
if (cursor < vmVersion.length()) {
|
||||
if (vmVersion.charAt(cursor) == 'b') {
|
||||
cursor++;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static String getJVMCIVersionString(int major, int minor) {
|
||||
if (major >= 19) {
|
||||
return String.format("%d-b%02d", major, minor);
|
||||
} else {
|
||||
return String.format("%d.%d", major, minor);
|
||||
}
|
||||
}
|
||||
|
||||
private void run(boolean exitOnFailure, int jvmci8MinMajorVersion, int jvmci8MinMinorVersion) {
|
||||
// Don't use regular expressions to minimize Graal startup time
|
||||
private void run(boolean exitOnFailure, Version minVersion) {
|
||||
if (javaSpecVersion.compareTo("1.9") < 0) {
|
||||
cursor = vmVersion.indexOf("-jvmci-");
|
||||
if (cursor >= 0) {
|
||||
cursor += "-jvmci-".length();
|
||||
int major = parseNumber();
|
||||
if (major == -1) {
|
||||
failVersionCheck(props, exitOnFailure, "The VM does not support the minimum JVMCI API version required by Graal.%n" +
|
||||
"Cannot read JVMCI major version from java.vm.version property: %s.%n", vmVersion);
|
||||
return;
|
||||
}
|
||||
|
||||
if (parseSeparator()) {
|
||||
int minor = parseNumber();
|
||||
if (minor == -1) {
|
||||
failVersionCheck(props, exitOnFailure, "The VM does not support the minimum JVMCI API version required by Graal.%n" +
|
||||
"Cannot read JVMCI minor version from java.vm.version property: %s.%n", vmVersion);
|
||||
return;
|
||||
}
|
||||
|
||||
if (major > jvmci8MinMajorVersion || (major >= jvmci8MinMajorVersion && minor >= jvmci8MinMinorVersion)) {
|
||||
return;
|
||||
}
|
||||
failVersionCheck(props, exitOnFailure, "The VM does not support the minimum JVMCI API version required by Graal: %s < %s.%n",
|
||||
getJVMCIVersionString(major, minor), getJVMCIVersionString(jvmci8MinMajorVersion, jvmci8MinMinorVersion));
|
||||
return;
|
||||
Version v = Version.parse(vmVersion);
|
||||
if (v != null) {
|
||||
if (v.isLessThan(minVersion)) {
|
||||
failVersionCheck(props, exitOnFailure, "The VM does not support the minimum JVMCI API version required by Graal: %s < %s.%n", v, minVersion);
|
||||
}
|
||||
return;
|
||||
}
|
||||
failVersionCheck(props, exitOnFailure, "The VM does not support the minimum JVMCI API version required by Graal.%n" +
|
||||
"Cannot read JVMCI version from java.vm.version property: %s.%n", vmVersion);
|
||||
|
@ -182,7 +182,7 @@ import jdk.vm.ci.meta.ResolvedJavaType;
|
||||
/**
|
||||
* HotSpot implementation of {@link LoweringProvider}.
|
||||
*/
|
||||
public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider implements HotSpotLoweringProvider {
|
||||
public abstract class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider implements HotSpotLoweringProvider {
|
||||
|
||||
protected final HotSpotGraalRuntimeProvider runtime;
|
||||
protected final HotSpotRegistersProvider registers;
|
||||
|
@ -44,6 +44,7 @@ import org.graalvm.compiler.core.common.spi.ForeignCallsProvider;
|
||||
import org.graalvm.compiler.core.common.type.ObjectStamp;
|
||||
import org.graalvm.compiler.core.common.type.StampFactory;
|
||||
import org.graalvm.compiler.core.common.type.TypeReference;
|
||||
import org.graalvm.compiler.debug.GraalError;
|
||||
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
|
||||
import org.graalvm.compiler.hotspot.nodes.CurrentJavaThreadNode;
|
||||
import org.graalvm.compiler.hotspot.replacements.AESCryptSubstitutions;
|
||||
@ -106,6 +107,7 @@ import org.graalvm.compiler.word.WordTypes;
|
||||
import jdk.internal.vm.compiler.word.LocationIdentity;
|
||||
|
||||
import jdk.vm.ci.code.CodeUtil;
|
||||
import jdk.vm.ci.hotspot.VMIntrinsicMethod;
|
||||
import jdk.vm.ci.meta.ConstantReflectionProvider;
|
||||
import jdk.vm.ci.meta.DeoptimizationAction;
|
||||
import jdk.vm.ci.meta.JavaKind;
|
||||
@ -429,8 +431,6 @@ public class HotSpotGraphBuilderPlugins {
|
||||
r.registerMethodSubstitution(ThreadSubstitutions.class, "isInterrupted", Receiver.class, boolean.class);
|
||||
}
|
||||
|
||||
public static final String cbcEncryptName;
|
||||
public static final String cbcDecryptName;
|
||||
public static final String aesEncryptName;
|
||||
public static final String aesDecryptName;
|
||||
|
||||
@ -439,15 +439,11 @@ public class HotSpotGraphBuilderPlugins {
|
||||
|
||||
static {
|
||||
if (JavaVersionUtil.JAVA_SPEC <= 8) {
|
||||
cbcEncryptName = "encrypt";
|
||||
cbcDecryptName = "decrypt";
|
||||
aesEncryptName = "encryptBlock";
|
||||
aesDecryptName = "decryptBlock";
|
||||
reflectionClass = "sun.reflect.Reflection";
|
||||
constantPoolClass = "sun.reflect.ConstantPool";
|
||||
} else {
|
||||
cbcEncryptName = "implEncrypt";
|
||||
cbcDecryptName = "implDecrypt";
|
||||
aesEncryptName = "implEncryptBlock";
|
||||
aesDecryptName = "implDecryptBlock";
|
||||
reflectionClass = "jdk.internal.reflect.Reflection";
|
||||
@ -455,6 +451,19 @@ public class HotSpotGraphBuilderPlugins {
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean cbcUsesImplNames(GraalHotSpotVMConfig config) {
|
||||
for (VMIntrinsicMethod intrinsic : config.getStore().getIntrinsics()) {
|
||||
if ("com/sun/crypto/provider/CipherBlockChaining".equals(intrinsic.declaringClass)) {
|
||||
if ("encrypt".equals(intrinsic.name)) {
|
||||
return false;
|
||||
} else if ("implEncrypt".equals(intrinsic.name)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
throw GraalError.shouldNotReachHere();
|
||||
}
|
||||
|
||||
private static void registerAESPlugins(InvocationPlugins plugins, GraalHotSpotVMConfig config, BytecodeProvider bytecodeProvider) {
|
||||
if (config.useAESIntrinsics) {
|
||||
assert config.aescryptEncryptBlockStub != 0L;
|
||||
@ -464,9 +473,15 @@ public class HotSpotGraphBuilderPlugins {
|
||||
String arch = config.osArch;
|
||||
String decryptSuffix = arch.equals("sparc") ? "WithOriginalKey" : "";
|
||||
Registration r = new Registration(plugins, "com.sun.crypto.provider.CipherBlockChaining", bytecodeProvider);
|
||||
|
||||
boolean implNames = cbcUsesImplNames(config);
|
||||
String cbcEncryptName = implNames ? "implEncrypt" : "encrypt";
|
||||
String cbcDecryptName = implNames ? "implDecrypt" : "decrypt";
|
||||
|
||||
r.registerMethodSubstitution(CipherBlockChainingSubstitutions.class, cbcEncryptName, Receiver.class, byte[].class, int.class, int.class, byte[].class, int.class);
|
||||
r.registerMethodSubstitution(CipherBlockChainingSubstitutions.class, cbcDecryptName, cbcDecryptName + decryptSuffix, Receiver.class, byte[].class, int.class, int.class, byte[].class,
|
||||
int.class);
|
||||
|
||||
r = new Registration(plugins, "com.sun.crypto.provider.AESCrypt", bytecodeProvider);
|
||||
r.registerMethodSubstitution(AESCryptSubstitutions.class, aesEncryptName, Receiver.class, byte[].class, int.class, byte[].class, int.class);
|
||||
r.registerMethodSubstitution(AESCryptSubstitutions.class, aesDecryptName, aesDecryptName + decryptSuffix, Receiver.class, byte[].class, int.class, byte[].class, int.class);
|
||||
|
@ -244,4 +244,3 @@ public final class HotSpotNodePlugin implements NodePlugin, TypePlugin {
|
||||
|
||||
private static final LocationIdentity JAVA_THREAD_SHOULD_POST_ON_EXCEPTIONS_FLAG_LOCATION = NamedLocationIdentity.mutable("JavaThread::_should_post_on_exceptions_flag");
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2019, 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 @@ import org.graalvm.compiler.loop.LoopsData;
|
||||
import org.graalvm.compiler.loop.phases.LoopTransformations;
|
||||
import org.graalvm.compiler.nodeinfo.InputType;
|
||||
import org.graalvm.compiler.nodeinfo.Verbosity;
|
||||
import org.graalvm.compiler.nodes.AbstractBeginNode;
|
||||
import org.graalvm.compiler.nodes.EntryMarkerNode;
|
||||
import org.graalvm.compiler.nodes.EntryProxyNode;
|
||||
import org.graalvm.compiler.nodes.FixedGuardNode;
|
||||
@ -159,11 +158,8 @@ public class OnStackReplacementPhase extends Phase {
|
||||
LoopEx loop = loops.loop(l);
|
||||
loop.loopBegin().markOsrLoop();
|
||||
LoopTransformations.peel(loop);
|
||||
osr.replaceAtUsages(InputType.Guard, AbstractBeginNode.prevBegin((FixedNode) osr.predecessor()));
|
||||
for (Node usage : osr.usages().snapshot()) {
|
||||
EntryProxyNode proxy = (EntryProxyNode) usage;
|
||||
proxy.replaceAndDelete(proxy.value());
|
||||
}
|
||||
|
||||
osr.prepareDelete();
|
||||
GraphUtil.removeFixedWithUnusedInputs(osr);
|
||||
debug.dump(DebugContext.DETAILED_LEVEL, graph, "OnStackReplacement loop peeling result");
|
||||
} while (true);
|
||||
@ -228,6 +224,7 @@ public class OnStackReplacementPhase extends Phase {
|
||||
}
|
||||
|
||||
osr.replaceAtUsages(InputType.Guard, osrStart);
|
||||
osr.replaceAtUsages(InputType.Anchor, osrStart);
|
||||
}
|
||||
debug.dump(DebugContext.DETAILED_LEVEL, graph, "OnStackReplacement after replacing entry proxies");
|
||||
GraphUtil.killCFG(start);
|
||||
|
@ -191,4 +191,3 @@ public final class Log {
|
||||
println("");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -212,14 +212,27 @@ public class NewObjectSnippets implements Snippets {
|
||||
}
|
||||
|
||||
@Snippet
|
||||
public static Object allocateInstance(@ConstantParameter long size, KlassPointer hub, Word prototypeMarkWord, @ConstantParameter boolean fillContents,
|
||||
@ConstantParameter Register threadRegister, @ConstantParameter boolean constantSize, @ConstantParameter String typeContext,
|
||||
public static Object allocateInstance(@ConstantParameter long size,
|
||||
KlassPointer hub,
|
||||
Word prototypeMarkWord,
|
||||
@ConstantParameter boolean fillContents,
|
||||
@ConstantParameter boolean emitMemoryBarrier,
|
||||
@ConstantParameter Register threadRegister,
|
||||
@ConstantParameter boolean constantSize,
|
||||
@ConstantParameter String typeContext,
|
||||
@ConstantParameter Counters counters) {
|
||||
return piCastToSnippetReplaceeStamp(allocateInstanceHelper(size, hub, prototypeMarkWord, fillContents, threadRegister, constantSize, typeContext, counters));
|
||||
return piCastToSnippetReplaceeStamp(allocateInstanceHelper(size, hub, prototypeMarkWord, fillContents, emitMemoryBarrier, threadRegister, constantSize, typeContext, counters));
|
||||
}
|
||||
|
||||
public static Object allocateInstanceHelper(long size, KlassPointer hub, Word prototypeMarkWord, boolean fillContents,
|
||||
Register threadRegister, boolean constantSize, String typeContext, Counters counters) {
|
||||
public static Object allocateInstanceHelper(long size,
|
||||
KlassPointer hub,
|
||||
Word prototypeMarkWord,
|
||||
boolean fillContents,
|
||||
boolean emitMemoryBarrier,
|
||||
Register threadRegister,
|
||||
boolean constantSize,
|
||||
String typeContext,
|
||||
Counters counters) {
|
||||
Object result;
|
||||
Word thread = registerAsWord(threadRegister);
|
||||
Word top = readTlabTop(thread);
|
||||
@ -228,7 +241,7 @@ public class NewObjectSnippets implements Snippets {
|
||||
if (useTLAB(INJECTED_VMCONFIG) && probability(FAST_PATH_PROBABILITY, newTop.belowOrEqual(end))) {
|
||||
writeTlabTop(thread, newTop);
|
||||
emitPrefetchAllocate(newTop, false);
|
||||
result = formatObject(hub, size, top, prototypeMarkWord, fillContents, constantSize, counters);
|
||||
result = formatObject(hub, size, top, prototypeMarkWord, fillContents, emitMemoryBarrier, constantSize, counters);
|
||||
} else {
|
||||
Counters theCounters = counters;
|
||||
if (theCounters != null && theCounters.stub != null) {
|
||||
@ -255,18 +268,27 @@ public class NewObjectSnippets implements Snippets {
|
||||
private static native Object newInstanceOrNull(@ConstantNodeParameter ForeignCallDescriptor descriptor, KlassPointer hub);
|
||||
|
||||
@Snippet
|
||||
public static Object allocateInstancePIC(@ConstantParameter long size, KlassPointer hub, Word prototypeMarkWord, @ConstantParameter boolean fillContents,
|
||||
@ConstantParameter Register threadRegister, @ConstantParameter boolean constantSize, @ConstantParameter String typeContext,
|
||||
public static Object allocateInstancePIC(@ConstantParameter long size,
|
||||
KlassPointer hub,
|
||||
Word prototypeMarkWord,
|
||||
@ConstantParameter boolean fillContents,
|
||||
@ConstantParameter boolean emitMemoryBarrier,
|
||||
@ConstantParameter Register threadRegister,
|
||||
@ConstantParameter boolean constantSize,
|
||||
@ConstantParameter String typeContext,
|
||||
@ConstantParameter Counters counters) {
|
||||
// Klass must be initialized by the time the first instance is allocated, therefore we can
|
||||
// just load it from the corresponding cell and avoid the resolution check. We have to use a
|
||||
// fixed load though, to prevent it from floating above the initialization.
|
||||
KlassPointer picHub = LoadConstantIndirectlyFixedNode.loadKlass(hub);
|
||||
return piCastToSnippetReplaceeStamp(allocateInstanceHelper(size, picHub, prototypeMarkWord, fillContents, threadRegister, constantSize, typeContext, counters));
|
||||
return piCastToSnippetReplaceeStamp(allocateInstanceHelper(size, picHub, prototypeMarkWord, fillContents, emitMemoryBarrier, threadRegister, constantSize, typeContext, counters));
|
||||
}
|
||||
|
||||
@Snippet
|
||||
public static Object allocateInstanceDynamic(Class<?> type, Class<?> classClass, @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister,
|
||||
public static Object allocateInstanceDynamic(Class<?> type, Class<?> classClass,
|
||||
@ConstantParameter boolean fillContents,
|
||||
@ConstantParameter boolean emitMemoryBarrier,
|
||||
@ConstantParameter Register threadRegister,
|
||||
@ConstantParameter Counters counters) {
|
||||
if (probability(SLOW_PATH_PROBABILITY, type == null)) {
|
||||
DeoptimizeNode.deopt(None, RuntimeConstraint);
|
||||
@ -277,10 +299,15 @@ public class NewObjectSnippets implements Snippets {
|
||||
DeoptimizeNode.deopt(None, RuntimeConstraint);
|
||||
}
|
||||
|
||||
return PiNode.piCastToSnippetReplaceeStamp(allocateInstanceDynamicHelper(type, fillContents, threadRegister, counters, nonNullType));
|
||||
return PiNode.piCastToSnippetReplaceeStamp(allocateInstanceDynamicHelper(type, fillContents, emitMemoryBarrier, threadRegister, counters, nonNullType));
|
||||
}
|
||||
|
||||
private static Object allocateInstanceDynamicHelper(Class<?> type, boolean fillContents, Register threadRegister, Counters counters, Class<?> nonNullType) {
|
||||
private static Object allocateInstanceDynamicHelper(Class<?> type,
|
||||
boolean fillContents,
|
||||
boolean emitMemoryBarrier,
|
||||
Register threadRegister,
|
||||
Counters counters,
|
||||
Class<?> nonNullType) {
|
||||
KlassPointer hub = ClassGetHubNode.readClass(nonNullType);
|
||||
if (probability(FAST_PATH_PROBABILITY, !hub.isNull())) {
|
||||
KlassPointer nonNullHub = ClassGetHubNode.piCastNonNull(hub, SnippetAnchorNode.anchor());
|
||||
@ -299,7 +326,7 @@ public class NewObjectSnippets implements Snippets {
|
||||
* FIXME(je,ds): we should actually pass typeContext instead of "" but late
|
||||
* binding of parameters is not yet supported by the GraphBuilderPlugin system.
|
||||
*/
|
||||
return allocateInstanceHelper(layoutHelper, nonNullHub, prototypeMarkWord, fillContents, threadRegister, false, "", counters);
|
||||
return allocateInstanceHelper(layoutHelper, nonNullHub, prototypeMarkWord, fillContents, emitMemoryBarrier, threadRegister, false, "", counters);
|
||||
}
|
||||
} else {
|
||||
DeoptimizeNode.deopt(None, RuntimeConstraint);
|
||||
@ -320,6 +347,7 @@ public class NewObjectSnippets implements Snippets {
|
||||
@ConstantParameter int headerSize,
|
||||
@ConstantParameter int log2ElementSize,
|
||||
@ConstantParameter boolean fillContents,
|
||||
@ConstantParameter boolean emitMemoryBarrier,
|
||||
@ConstantParameter Register threadRegister,
|
||||
@ConstantParameter boolean maybeUnroll,
|
||||
@ConstantParameter String typeContext,
|
||||
@ -328,7 +356,7 @@ public class NewObjectSnippets implements Snippets {
|
||||
// Primitive array types are eagerly pre-resolved. We can use a floating load.
|
||||
KlassPointer picHub = LoadConstantIndirectlyNode.loadKlass(hub);
|
||||
return allocateArrayImpl(picHub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents,
|
||||
threadRegister, maybeUnroll, typeContext, useBulkZeroing, counters);
|
||||
emitMemoryBarrier, threadRegister, maybeUnroll, typeContext, useBulkZeroing, counters);
|
||||
}
|
||||
|
||||
@Snippet
|
||||
@ -338,6 +366,7 @@ public class NewObjectSnippets implements Snippets {
|
||||
@ConstantParameter int headerSize,
|
||||
@ConstantParameter int log2ElementSize,
|
||||
@ConstantParameter boolean fillContents,
|
||||
@ConstantParameter boolean emitMemoryBarrier,
|
||||
@ConstantParameter Register threadRegister,
|
||||
@ConstantParameter boolean maybeUnroll,
|
||||
@ConstantParameter String typeContext,
|
||||
@ -346,7 +375,7 @@ public class NewObjectSnippets implements Snippets {
|
||||
// Array type would be resolved by dominating resolution.
|
||||
KlassPointer picHub = LoadConstantIndirectlyFixedNode.loadKlass(hub);
|
||||
return allocateArrayImpl(picHub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents,
|
||||
threadRegister, maybeUnroll, typeContext, useBulkZeroing, counters);
|
||||
emitMemoryBarrier, threadRegister, maybeUnroll, typeContext, useBulkZeroing, counters);
|
||||
}
|
||||
|
||||
@Snippet
|
||||
@ -356,6 +385,7 @@ public class NewObjectSnippets implements Snippets {
|
||||
@ConstantParameter int headerSize,
|
||||
@ConstantParameter int log2ElementSize,
|
||||
@ConstantParameter boolean fillContents,
|
||||
@ConstantParameter boolean emitMemoryBarrier,
|
||||
@ConstantParameter Register threadRegister,
|
||||
@ConstantParameter boolean maybeUnroll,
|
||||
@ConstantParameter String typeContext,
|
||||
@ -367,7 +397,7 @@ public class NewObjectSnippets implements Snippets {
|
||||
headerSize,
|
||||
log2ElementSize,
|
||||
fillContents,
|
||||
threadRegister,
|
||||
emitMemoryBarrier, threadRegister,
|
||||
maybeUnroll,
|
||||
typeContext,
|
||||
useBulkZeroing,
|
||||
@ -384,8 +414,18 @@ public class NewObjectSnippets implements Snippets {
|
||||
return config.areNullAllocationStubsAvailable();
|
||||
}
|
||||
|
||||
private static Object allocateArrayImpl(KlassPointer hub, int length, Word prototypeMarkWord, int headerSize, int log2ElementSize, boolean fillContents, Register threadRegister,
|
||||
boolean maybeUnroll, String typeContext, boolean useBulkZeroing, Counters counters) {
|
||||
private static Object allocateArrayImpl(KlassPointer hub,
|
||||
int length,
|
||||
Word prototypeMarkWord,
|
||||
int headerSize,
|
||||
int log2ElementSize,
|
||||
boolean fillContents,
|
||||
boolean emitMemoryBarrier,
|
||||
Register threadRegister,
|
||||
boolean maybeUnroll,
|
||||
String typeContext,
|
||||
boolean useBulkZeroing,
|
||||
Counters counters) {
|
||||
Object result;
|
||||
long allocationSize = arrayAllocationSize(length, headerSize, log2ElementSize);
|
||||
Word thread = registerAsWord(threadRegister);
|
||||
@ -400,7 +440,7 @@ public class NewObjectSnippets implements Snippets {
|
||||
if (theCounters != null && theCounters.arrayLoopInit != null) {
|
||||
theCounters.arrayLoopInit.inc();
|
||||
}
|
||||
result = formatArray(hub, allocationSize, length, headerSize, top, prototypeMarkWord, fillContents, maybeUnroll, useBulkZeroing, counters);
|
||||
result = formatArray(hub, allocationSize, length, headerSize, top, prototypeMarkWord, fillContents, emitMemoryBarrier, maybeUnroll, useBulkZeroing, counters);
|
||||
} else {
|
||||
result = newArrayStub(hub, length);
|
||||
}
|
||||
@ -461,19 +501,29 @@ public class NewObjectSnippets implements Snippets {
|
||||
Class<?> voidClass,
|
||||
int length,
|
||||
@ConstantParameter boolean fillContents,
|
||||
@ConstantParameter boolean emitMemoryBarrier,
|
||||
@ConstantParameter Register threadRegister,
|
||||
@ConstantParameter JavaKind knownElementKind,
|
||||
@ConstantParameter int knownLayoutHelper,
|
||||
@ConstantParameter boolean useBulkZeroing,
|
||||
Word prototypeMarkWord,
|
||||
@ConstantParameter Counters counters) {
|
||||
Object result = allocateArrayDynamicImpl(elementType, voidClass, length, fillContents, threadRegister, knownElementKind,
|
||||
Object result = allocateArrayDynamicImpl(elementType, voidClass, length, fillContents, emitMemoryBarrier, threadRegister, knownElementKind,
|
||||
knownLayoutHelper, useBulkZeroing, prototypeMarkWord, counters);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static Object allocateArrayDynamicImpl(Class<?> elementType, Class<?> voidClass, int length, boolean fillContents, Register threadRegister, JavaKind knownElementKind,
|
||||
int knownLayoutHelper, boolean useBulkZeroing, Word prototypeMarkWord, Counters counters) {
|
||||
private static Object allocateArrayDynamicImpl(Class<?> elementType,
|
||||
Class<?> voidClass,
|
||||
int length,
|
||||
boolean fillContents,
|
||||
boolean emitMemoryBarrier,
|
||||
Register threadRegister,
|
||||
JavaKind knownElementKind,
|
||||
int knownLayoutHelper,
|
||||
boolean useBulkZeroing,
|
||||
Word prototypeMarkWord,
|
||||
Counters counters) {
|
||||
/*
|
||||
* We only need the dynamic check for void when we have no static information from
|
||||
* knownElementKind.
|
||||
@ -516,7 +566,7 @@ public class NewObjectSnippets implements Snippets {
|
||||
int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift(INJECTED_VMCONFIG)) & layoutHelperLog2ElementSizeMask(INJECTED_VMCONFIG);
|
||||
|
||||
Object result = allocateArrayImpl(nonNullKlass, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents,
|
||||
threadRegister, false, "dynamic type", useBulkZeroing, counters);
|
||||
emitMemoryBarrier, threadRegister, false, "dynamic type", useBulkZeroing, counters);
|
||||
return piArrayCastToSnippetReplaceeStamp(verifyOop(result), length);
|
||||
}
|
||||
|
||||
@ -650,7 +700,14 @@ public class NewObjectSnippets implements Snippets {
|
||||
/**
|
||||
* Formats some allocated memory with an object header and zeroes out the rest.
|
||||
*/
|
||||
private static Object formatObject(KlassPointer hub, long size, Word memory, Word compileTimePrototypeMarkWord, boolean fillContents, boolean constantSize, Counters counters) {
|
||||
private static Object formatObject(KlassPointer hub,
|
||||
long size,
|
||||
Word memory,
|
||||
Word compileTimePrototypeMarkWord,
|
||||
boolean fillContents,
|
||||
boolean emitMemoryBarrier,
|
||||
boolean constantSize,
|
||||
Counters counters) {
|
||||
Word prototypeMarkWord = useBiasedLocking(INJECTED_VMCONFIG) ? hub.readWord(prototypeMarkWordOffset(INJECTED_VMCONFIG), PROTOTYPE_MARK_WORD_LOCATION) : compileTimePrototypeMarkWord;
|
||||
initializeObjectHeader(memory, prototypeMarkWord, hub);
|
||||
if (fillContents) {
|
||||
@ -658,7 +715,9 @@ public class NewObjectSnippets implements Snippets {
|
||||
} else if (REPLACEMENTS_ASSERTIONS_ENABLED) {
|
||||
fillWithGarbage(size, memory, constantSize, instanceHeaderSize(INJECTED_VMCONFIG), false, counters);
|
||||
}
|
||||
MembarNode.memoryBarrier(MemoryBarriers.STORE_STORE, LocationIdentity.init());
|
||||
if (emitMemoryBarrier) {
|
||||
MembarNode.memoryBarrier(MemoryBarriers.STORE_STORE, LocationIdentity.init());
|
||||
}
|
||||
return memory.toObjectNonNull();
|
||||
}
|
||||
|
||||
@ -677,8 +736,17 @@ public class NewObjectSnippets implements Snippets {
|
||||
/**
|
||||
* Formats some allocated memory with an object header and zeroes out the rest.
|
||||
*/
|
||||
private static Object formatArray(KlassPointer hub, long allocationSize, int length, int headerSize, Word memory, Word prototypeMarkWord, boolean fillContents, boolean maybeUnroll,
|
||||
boolean useBulkZeroing, Counters counters) {
|
||||
private static Object formatArray(KlassPointer hub,
|
||||
long allocationSize,
|
||||
int length,
|
||||
int headerSize,
|
||||
Word memory,
|
||||
Word prototypeMarkWord,
|
||||
boolean fillContents,
|
||||
boolean emitMemoryBarrier,
|
||||
boolean maybeUnroll,
|
||||
boolean useBulkZeroing,
|
||||
Counters counters) {
|
||||
memory.writeInt(arrayLengthOffset(INJECTED_VMCONFIG), length, LocationIdentity.init());
|
||||
/*
|
||||
* store hub last as the concurrent garbage collectors assume length is valid if hub field
|
||||
@ -690,7 +758,9 @@ public class NewObjectSnippets implements Snippets {
|
||||
} else if (REPLACEMENTS_ASSERTIONS_ENABLED) {
|
||||
fillWithGarbage(allocationSize, memory, false, headerSize, maybeUnroll, counters);
|
||||
}
|
||||
MembarNode.memoryBarrier(MemoryBarriers.STORE_STORE, LocationIdentity.init());
|
||||
if (emitMemoryBarrier) {
|
||||
MembarNode.memoryBarrier(MemoryBarriers.STORE_STORE, LocationIdentity.init());
|
||||
}
|
||||
return memory.toObjectNonNull();
|
||||
}
|
||||
|
||||
@ -756,6 +826,7 @@ public class NewObjectSnippets implements Snippets {
|
||||
args.add("hub", hub);
|
||||
args.add("prototypeMarkWord", type.prototypeMarkWord());
|
||||
args.addConst("fillContents", newInstanceNode.fillContents());
|
||||
args.addConst("emitMemoryBarrier", newInstanceNode.emitMemoryBarrier());
|
||||
args.addConst("threadRegister", registers.getThreadRegister());
|
||||
args.addConst("constantSize", true);
|
||||
args.addConst("typeContext", ProfileAllocations.getValue(localOptions) ? type.toJavaName(false) : "");
|
||||
@ -799,6 +870,7 @@ public class NewObjectSnippets implements Snippets {
|
||||
args.addConst("headerSize", headerSize);
|
||||
args.addConst("log2ElementSize", log2ElementSize);
|
||||
args.addConst("fillContents", newArrayNode.fillContents());
|
||||
args.addConst("emitMemoryBarrier", newArrayNode.emitMemoryBarrier());
|
||||
args.addConst("threadRegister", registers.getThreadRegister());
|
||||
args.addConst("maybeUnroll", length.isConstant());
|
||||
args.addConst("typeContext", ProfileAllocations.getValue(localOptions) ? arrayType.toJavaName(false) : "");
|
||||
@ -816,6 +888,7 @@ public class NewObjectSnippets implements Snippets {
|
||||
assert classClass != null;
|
||||
args.add("classClass", classClass);
|
||||
args.addConst("fillContents", newInstanceNode.fillContents());
|
||||
args.addConst("emitMemoryBarrier", newInstanceNode.emitMemoryBarrier());
|
||||
args.addConst("threadRegister", registers.getThreadRegister());
|
||||
args.addConst("counters", counters);
|
||||
|
||||
@ -833,6 +906,7 @@ public class NewObjectSnippets implements Snippets {
|
||||
ValueNode length = newArrayNode.length();
|
||||
args.add("length", length.isAlive() ? length : graph.addOrUniqueWithInputs(length));
|
||||
args.addConst("fillContents", newArrayNode.fillContents());
|
||||
args.addConst("emitMemoryBarrier", newArrayNode.emitMemoryBarrier());
|
||||
args.addConst("threadRegister", registers.getThreadRegister());
|
||||
/*
|
||||
* We use Kind.Illegal as a marker value instead of null because constant snippet
|
||||
|
@ -391,7 +391,6 @@ import org.graalvm.compiler.nodes.extended.LoadArrayComponentHubNode;
|
||||
import org.graalvm.compiler.nodes.extended.LoadHubNode;
|
||||
import org.graalvm.compiler.nodes.extended.MembarNode;
|
||||
import org.graalvm.compiler.nodes.extended.StateSplitProxyNode;
|
||||
import org.graalvm.compiler.nodes.extended.ValueAnchorNode;
|
||||
import org.graalvm.compiler.nodes.graphbuilderconf.ClassInitializationPlugin;
|
||||
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
|
||||
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.BytecodeExceptionMode;
|
||||
@ -624,7 +623,6 @@ public class BytecodeParser implements GraphBuilderContext {
|
||||
}
|
||||
|
||||
static class IntrinsicScope extends InliningScope {
|
||||
StateSplit returnStateSplit;
|
||||
ArrayList<StateSplit> invalidStateUsers;
|
||||
|
||||
IntrinsicScope(BytecodeParser parser) {
|
||||
@ -635,6 +633,7 @@ public class BytecodeParser implements GraphBuilderContext {
|
||||
super(parser, callee, args);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unlikely-arg-type")
|
||||
@Override
|
||||
public void close() {
|
||||
IntrinsicContext intrinsic = parser.intrinsicContext;
|
||||
@ -1405,7 +1404,7 @@ public class BytecodeParser implements GraphBuilderContext {
|
||||
if (profile == null || profile.getNotRecordedProbability() > 0.0) {
|
||||
return null;
|
||||
} else {
|
||||
return append(new ValueAnchorNode(null));
|
||||
return BeginNode.prevBegin(lastInstr);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4794,6 +4793,9 @@ public class BytecodeParser implements GraphBuilderContext {
|
||||
}
|
||||
}
|
||||
|
||||
private static final int SWITCH_DEOPT_UNSEEN = -2;
|
||||
private static final int SWITCH_DEOPT_SEEN = -1;
|
||||
|
||||
private void genSwitch(BytecodeSwitch bs) {
|
||||
int bci = bci();
|
||||
ValueNode value = frameState.pop(JavaKind.Int);
|
||||
@ -4811,20 +4813,16 @@ public class BytecodeParser implements GraphBuilderContext {
|
||||
ArrayList<BciBlock> actualSuccessors = new ArrayList<>();
|
||||
int[] keys = new int[nofCases];
|
||||
int[] keySuccessors = new int[nofCasesPlusDefault];
|
||||
int deoptSuccessorIndex = -1;
|
||||
int deoptSuccessorIndex = SWITCH_DEOPT_UNSEEN;
|
||||
int nextSuccessorIndex = 0;
|
||||
boolean constantValue = value.isConstant();
|
||||
for (int i = 0; i < nofCasesPlusDefault; i++) {
|
||||
if (i < nofCases) {
|
||||
keys[i] = bs.keyAt(i);
|
||||
}
|
||||
|
||||
if (!constantValue && isNeverExecutedCode(keyProbabilities[i])) {
|
||||
if (deoptSuccessorIndex < 0) {
|
||||
deoptSuccessorIndex = nextSuccessorIndex++;
|
||||
actualSuccessors.add(null);
|
||||
}
|
||||
keySuccessors[i] = deoptSuccessorIndex;
|
||||
deoptSuccessorIndex = SWITCH_DEOPT_SEEN;
|
||||
keySuccessors[i] = SWITCH_DEOPT_SEEN;
|
||||
} else {
|
||||
int targetBci = i < nofCases ? bs.targetAt(i) : bs.defaultTarget();
|
||||
SuccessorInfo info = bciToBlockSuccessorIndex.get(targetBci);
|
||||
@ -4859,20 +4857,31 @@ public class BytecodeParser implements GraphBuilderContext {
|
||||
*
|
||||
* The following code rewires deoptimization stub to existing resolved branch target if
|
||||
* the target is connected by more than 1 cases.
|
||||
*
|
||||
* If this operation rewires every deoptimization seen to an existing branch, care is
|
||||
* taken that we do not spawn a branch that will never be taken.
|
||||
*/
|
||||
if (deoptSuccessorIndex >= 0) {
|
||||
int[] connectedCases = new int[nextSuccessorIndex];
|
||||
if (deoptSuccessorIndex == SWITCH_DEOPT_SEEN) {
|
||||
int[] connectedCases = new int[nextSuccessorIndex + 1];
|
||||
for (int i = 0; i < nofCasesPlusDefault; i++) {
|
||||
connectedCases[keySuccessors[i]]++;
|
||||
connectedCases[keySuccessors[i] + 1]++;
|
||||
}
|
||||
|
||||
for (int i = 0; i < nofCasesPlusDefault; i++) {
|
||||
if (keySuccessors[i] == deoptSuccessorIndex) {
|
||||
if (keySuccessors[i] == SWITCH_DEOPT_SEEN) {
|
||||
int targetBci = i < nofCases ? bs.targetAt(i) : bs.defaultTarget();
|
||||
SuccessorInfo info = bciToBlockSuccessorIndex.get(targetBci);
|
||||
int rewiredIndex = info.actualIndex;
|
||||
if (rewiredIndex >= 0 && connectedCases[rewiredIndex] > 1) {
|
||||
if (rewiredIndex >= 0 && connectedCases[rewiredIndex + 1] > 1) {
|
||||
// Rewire
|
||||
keySuccessors[i] = info.actualIndex;
|
||||
} else {
|
||||
if (deoptSuccessorIndex == SWITCH_DEOPT_SEEN) {
|
||||
// Spawn deopt successor if needed.
|
||||
deoptSuccessorIndex = nextSuccessorIndex++;
|
||||
actualSuccessors.add(null);
|
||||
}
|
||||
keySuccessors[i] = deoptSuccessorIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -528,8 +528,8 @@ public class AArch64Move {
|
||||
break;
|
||||
case Object:
|
||||
if (input.isNull()) {
|
||||
if (crb.mustReplaceWithNullRegister(input)) {
|
||||
masm.mov(64, dst, crb.nullRegister);
|
||||
if (crb.mustReplaceWithUncompressedNullRegister(input)) {
|
||||
masm.mov(64, dst, crb.uncompressedNullRegister);
|
||||
} else {
|
||||
masm.mov(dst, 0);
|
||||
}
|
||||
@ -725,7 +725,7 @@ public class AArch64Move {
|
||||
|
||||
@Override
|
||||
public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) {
|
||||
Register nullRegister = crb.nullRegister;
|
||||
Register nullRegister = crb.uncompressedNullRegister;
|
||||
if (!nullRegister.equals(Register.None)) {
|
||||
emitConversion(asRegister(result), asRegister(input), nullRegister, masm);
|
||||
}
|
||||
|
@ -645,4 +645,3 @@ public final class AMD64ArrayIndexOfOp extends AMD64LIRInstruction {
|
||||
return ((AMD64) tool.target().arch).getFeatures().contains(cpuFeature);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -213,7 +213,7 @@ public class AMD64ControlFlow {
|
||||
masm.cmpq(keyRegister, (AMD64Address) crb.asLongConstRef(jc));
|
||||
break;
|
||||
case Object:
|
||||
AMD64Move.const2reg(crb, masm, asRegister(scratch), jc);
|
||||
AMD64Move.const2reg(crb, masm, asRegister(scratch), jc, AMD64Kind.QWORD);
|
||||
masm.cmpptr(keyRegister, asRegister(scratch));
|
||||
break;
|
||||
default:
|
||||
|
@ -156,7 +156,7 @@ public class AMD64Move {
|
||||
@Override
|
||||
public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
|
||||
if (isRegister(result)) {
|
||||
const2reg(crb, masm, asRegister(result), input);
|
||||
const2reg(crb, masm, asRegister(result), input, (AMD64Kind) result.getPlatformKind());
|
||||
} else {
|
||||
assert isStackSlot(result);
|
||||
const2stack(crb, masm, result, input);
|
||||
@ -557,7 +557,7 @@ public class AMD64Move {
|
||||
}
|
||||
} else if (isJavaConstant(input)) {
|
||||
if (isRegister(result)) {
|
||||
const2reg(crb, masm, asRegister(result), asJavaConstant(input));
|
||||
const2reg(crb, masm, asRegister(result), asJavaConstant(input), moveKind);
|
||||
} else if (isStackSlot(result)) {
|
||||
const2stack(crb, masm, result, asJavaConstant(input));
|
||||
} else {
|
||||
@ -645,7 +645,7 @@ public class AMD64Move {
|
||||
}
|
||||
}
|
||||
|
||||
public static void const2reg(CompilationResultBuilder crb, AMD64MacroAssembler masm, Register result, JavaConstant input) {
|
||||
public static void const2reg(CompilationResultBuilder crb, AMD64MacroAssembler masm, Register result, JavaConstant input, AMD64Kind moveKind) {
|
||||
/*
|
||||
* Note: we use the kind of the input operand (and not the kind of the result operand)
|
||||
* because they don't match in all cases. For example, an object constant can be loaded to a
|
||||
@ -691,20 +691,34 @@ public class AMD64Move {
|
||||
}
|
||||
break;
|
||||
case Object:
|
||||
assert moveKind != null : "a nun-null moveKind is required for loading an object constant";
|
||||
// Do not optimize with an XOR as this instruction may be between
|
||||
// a CMP and a Jcc in which case the XOR will modify the condition
|
||||
// flags and interfere with the Jcc.
|
||||
if (input.isNull()) {
|
||||
if (crb.mustReplaceWithNullRegister(input)) {
|
||||
masm.movq(result, crb.nullRegister);
|
||||
if (moveKind == AMD64Kind.QWORD && crb.mustReplaceWithUncompressedNullRegister(input)) {
|
||||
masm.movq(result, crb.uncompressedNullRegister);
|
||||
} else {
|
||||
// Upper bits will be zeroed so this also works for narrow oops
|
||||
masm.movslq(result, 0);
|
||||
}
|
||||
} else if (crb.target.inlineObjects) {
|
||||
crb.recordInlineDataInCode(input);
|
||||
masm.movq(result, 0xDEADDEADDEADDEADL, true);
|
||||
} else {
|
||||
masm.movq(result, (AMD64Address) crb.recordDataReferenceInCode(input, 0));
|
||||
if (crb.target.inlineObjects) {
|
||||
crb.recordInlineDataInCode(input);
|
||||
if (moveKind == AMD64Kind.DWORD) {
|
||||
// Support for narrow oops
|
||||
masm.movl(result, 0xDEADDEAD, true);
|
||||
} else {
|
||||
masm.movq(result, 0xDEADDEADDEADDEADL, true);
|
||||
}
|
||||
} else {
|
||||
if (moveKind == AMD64Kind.DWORD) {
|
||||
// Support for narrow oops
|
||||
masm.movl(result, (AMD64Address) crb.recordDataReferenceInCode(input, 0));
|
||||
} else {
|
||||
masm.movq(result, (AMD64Address) crb.recordDataReferenceInCode(input, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -752,13 +766,13 @@ public class AMD64Move {
|
||||
break;
|
||||
case Object:
|
||||
if (input.isNull()) {
|
||||
if (crb.mustReplaceWithNullRegister(input)) {
|
||||
masm.movq(dest, crb.nullRegister);
|
||||
if (crb.mustReplaceWithUncompressedNullRegister(input)) {
|
||||
masm.movq(dest, crb.uncompressedNullRegister);
|
||||
return;
|
||||
}
|
||||
imm = 0;
|
||||
} else {
|
||||
throw GraalError.shouldNotReachHere("Non-null object constants must be in register");
|
||||
throw GraalError.shouldNotReachHere("Non-null object constants must be in a register");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -941,7 +955,7 @@ public class AMD64Move {
|
||||
|
||||
@Override
|
||||
public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
|
||||
Register nullRegister = crb.nullRegister;
|
||||
Register nullRegister = crb.uncompressedNullRegister;
|
||||
if (!nullRegister.equals(Register.None)) {
|
||||
emitConversion(asRegister(result), asRegister(input), nullRegister, masm);
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp;
|
||||
import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
|
||||
import org.graalvm.compiler.lir.framemap.FrameMap;
|
||||
|
||||
import jdk.vm.ci.amd64.AMD64Kind;
|
||||
import jdk.vm.ci.code.Register;
|
||||
import jdk.vm.ci.code.RegisterSaveLayout;
|
||||
import jdk.vm.ci.meta.JavaConstant;
|
||||
@ -66,7 +67,7 @@ public final class AMD64ZapRegistersOp extends AMD64LIRInstruction implements Sa
|
||||
for (int i = 0; i < zappedRegisters.length; i++) {
|
||||
Register reg = zappedRegisters[i];
|
||||
if (reg != null) {
|
||||
AMD64Move.const2reg(crb, masm, reg, zapValues[i]);
|
||||
AMD64Move.const2reg(crb, masm, reg, zapValues[i], AMD64Kind.QWORD);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2019, 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,6 +35,7 @@ import org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRRIOp;
|
||||
import org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRVMOp;
|
||||
import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
|
||||
import org.graalvm.compiler.asm.amd64.AVXKind;
|
||||
import org.graalvm.compiler.lir.ConstantValue;
|
||||
import org.graalvm.compiler.lir.LIRFrameState;
|
||||
import org.graalvm.compiler.lir.LIRInstructionClass;
|
||||
import org.graalvm.compiler.lir.Opcode;
|
||||
@ -42,6 +43,7 @@ import org.graalvm.compiler.lir.amd64.AMD64AddressValue;
|
||||
import org.graalvm.compiler.lir.amd64.AMD64LIRInstruction;
|
||||
import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
|
||||
|
||||
import jdk.vm.ci.amd64.AMD64Kind;
|
||||
import jdk.vm.ci.meta.AllocatableValue;
|
||||
|
||||
public class AMD64VectorBinary {
|
||||
@ -102,6 +104,38 @@ public class AMD64VectorBinary {
|
||||
}
|
||||
}
|
||||
|
||||
public static final class AVXBinaryConstFloatOp extends AMD64LIRInstruction {
|
||||
|
||||
public static final LIRInstructionClass<AVXBinaryConstFloatOp> TYPE = LIRInstructionClass.create(AVXBinaryConstFloatOp.class);
|
||||
|
||||
@Opcode private final VexRVMOp opcode;
|
||||
private final AVXKind.AVXSize size;
|
||||
|
||||
@Def({REG}) protected AllocatableValue result;
|
||||
@Use({REG}) protected AllocatableValue x;
|
||||
protected ConstantValue y;
|
||||
|
||||
public AVXBinaryConstFloatOp(VexRVMOp opcode, AVXKind.AVXSize size, AllocatableValue result, AllocatableValue x, ConstantValue y) {
|
||||
super(TYPE);
|
||||
assert y.getPlatformKind() == AMD64Kind.SINGLE || y.getPlatformKind() == AMD64Kind.DOUBLE;
|
||||
this.opcode = opcode;
|
||||
this.size = size;
|
||||
this.result = result;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
|
||||
if (y.getPlatformKind() == AMD64Kind.SINGLE) {
|
||||
opcode.emit(masm, size, asRegister(result), asRegister(x), (AMD64Address) crb.asFloatConstRef(y.getJavaConstant()));
|
||||
} else {
|
||||
assert y.getPlatformKind() == AMD64Kind.DOUBLE;
|
||||
opcode.emit(masm, size, asRegister(result), asRegister(x), (AMD64Address) crb.asDoubleConstRef(y.getJavaConstant()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static final class AVXBinaryMemoryOp extends AMD64LIRInstruction {
|
||||
public static final LIRInstructionClass<AVXBinaryMemoryOp> TYPE = LIRInstructionClass.create(AVXBinaryMemoryOp.class);
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2019, 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
|
||||
@ -99,7 +99,7 @@ public class ConstantStackCastTest extends LIRTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runByte() throws Throwable {
|
||||
public void runByte() {
|
||||
runTest("testByte", (byte) 0);
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2019, 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
|
||||
@ -254,7 +254,7 @@ public abstract class LIRTest extends JTTTest {
|
||||
|
||||
@java.lang.annotation.Retention(RetentionPolicy.RUNTIME)
|
||||
@java.lang.annotation.Target(ElementType.METHOD)
|
||||
public static @interface LIRIntrinsic {
|
||||
public @interface LIRIntrinsic {
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2019, 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
|
||||
@ -54,7 +54,7 @@ public class LIRTestTest extends LIRTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runInt() throws Throwable {
|
||||
public void runInt() {
|
||||
runTest("testGetOutput", Integer.MIN_VALUE, 0, supply(() -> new int[3]));
|
||||
runTest("testGetOutput", -1, Integer.MAX_VALUE, supply(() -> new int[3]));
|
||||
runTest("testGetOutput", 0, 42, supply(() -> new int[3]));
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2019, 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
|
||||
@ -98,7 +98,7 @@ public class StackMoveTest extends LIRTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runInt() throws Throwable {
|
||||
public void runInt() {
|
||||
runTest("testInt", Integer.MIN_VALUE, supply(() -> new int[4]));
|
||||
runTest("testInt", -1, supply(() -> new int[4]));
|
||||
runTest("testInt", 0, supply(() -> new int[4]));
|
||||
@ -125,7 +125,7 @@ public class StackMoveTest extends LIRTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runLong() throws Throwable {
|
||||
public void runLong() {
|
||||
runTest("testLong", Long.MIN_VALUE, supply(() -> new long[3]));
|
||||
runTest("testLong", -1L, supply(() -> new long[3]));
|
||||
runTest("testLong", 0L, supply(() -> new long[3]));
|
||||
@ -152,7 +152,7 @@ public class StackMoveTest extends LIRTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runFloat() throws Throwable {
|
||||
public void runFloat() {
|
||||
runTest("testFloat", Float.MIN_VALUE, supply(() -> new float[3]));
|
||||
runTest("testFloat", -1f, supply(() -> new float[3]));
|
||||
runTest("testFloat", -0.1f, supply(() -> new float[3]));
|
||||
@ -217,7 +217,7 @@ public class StackMoveTest extends LIRTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runShort() throws Throwable {
|
||||
public void runShort() {
|
||||
runTest("testShort", Short.MIN_VALUE, supply(() -> new short[3]));
|
||||
runTest("testShort", (short) -1, supply(() -> new short[3]));
|
||||
runTest("testShort", (short) 0, supply(() -> new short[3]));
|
||||
@ -251,7 +251,7 @@ public class StackMoveTest extends LIRTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runByte() throws Throwable {
|
||||
public void runByte() {
|
||||
runTest("testByte", Byte.MIN_VALUE, supply(() -> new byte[3]));
|
||||
runTest("testByte", (byte) -1, supply(() -> new byte[3]));
|
||||
runTest("testByte", (byte) 0, supply(() -> new byte[3]));
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2019, 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.
|
||||
*
|
||||
@ -139,7 +139,7 @@ public class StackStoreLoadTest extends LIRTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runByte() throws Throwable {
|
||||
public void runByte() {
|
||||
runTest("testByte", Byte.MIN_VALUE, supply(() -> new byte[3]));
|
||||
runTest("testByte", (byte) -1, supply(() -> new byte[3]));
|
||||
runTest("testByte", (byte) 0, supply(() -> new byte[3]));
|
||||
|
@ -25,7 +25,7 @@
|
||||
package org.graalvm.compiler.lir;
|
||||
|
||||
import static org.graalvm.compiler.lir.LIRValueUtil.asVariable;
|
||||
import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant;
|
||||
import static org.graalvm.compiler.lir.LIRValueUtil.isConstantValue;
|
||||
import static org.graalvm.compiler.lir.LIRValueUtil.isStackSlotValue;
|
||||
import static org.graalvm.compiler.lir.LIRValueUtil.isVariable;
|
||||
import static jdk.vm.ci.code.ValueUtil.asRegister;
|
||||
@ -242,7 +242,7 @@ public final class LIRVerifier {
|
||||
if ((isVariable(value) && flags.contains(OperandFlag.REG)) ||
|
||||
(isRegister(value) && flags.contains(OperandFlag.REG)) ||
|
||||
(isStackSlotValue(value) && flags.contains(OperandFlag.STACK)) ||
|
||||
(isJavaConstant(value) && flags.contains(OperandFlag.CONST) && mode != OperandMode.DEF) ||
|
||||
(isConstantValue(value) && flags.contains(OperandFlag.CONST) && mode != OperandMode.DEF) ||
|
||||
(isIllegal(value) && flags.contains(OperandFlag.ILLEGAL))) {
|
||||
return;
|
||||
}
|
||||
|
@ -35,6 +35,7 @@ import java.util.EnumSet;
|
||||
|
||||
import jdk.internal.vm.compiler.collections.EconomicSet;
|
||||
import org.graalvm.compiler.asm.Label;
|
||||
import org.graalvm.compiler.core.common.GraalOptions;
|
||||
import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
|
||||
import org.graalvm.compiler.debug.GraalError;
|
||||
import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
|
||||
@ -154,7 +155,7 @@ public class StandardOp {
|
||||
@Override
|
||||
public void emitCode(CompilationResultBuilder crb) {
|
||||
if (align) {
|
||||
crb.asm.align(crb.target.wordSize * 2);
|
||||
crb.asm.align(GraalOptions.LoopHeaderAlignment.getValue(crb.getOptions()));
|
||||
}
|
||||
crb.asm.bind(label);
|
||||
}
|
||||
|
@ -127,7 +127,7 @@ public class CompilationResultBuilder {
|
||||
public final Assembler asm;
|
||||
public final DataBuilder dataBuilder;
|
||||
public final CompilationResult compilationResult;
|
||||
public final Register nullRegister;
|
||||
public final Register uncompressedNullRegister;
|
||||
public final TargetDescription target;
|
||||
public final CodeCacheProvider codeCache;
|
||||
public final ForeignCallsProvider foreignCalls;
|
||||
@ -171,17 +171,44 @@ public class CompilationResultBuilder {
|
||||
*/
|
||||
private boolean conservativeLabelOffsets = false;
|
||||
|
||||
public final boolean mustReplaceWithNullRegister(JavaConstant nullConstant) {
|
||||
return !nullRegister.equals(Register.None) && JavaConstant.NULL_POINTER.equals(nullConstant);
|
||||
public final boolean mustReplaceWithUncompressedNullRegister(JavaConstant nullConstant) {
|
||||
return !uncompressedNullRegister.equals(Register.None) && JavaConstant.NULL_POINTER.equals(nullConstant);
|
||||
}
|
||||
|
||||
public CompilationResultBuilder(CodeCacheProvider codeCache, ForeignCallsProvider foreignCalls, FrameMap frameMap, Assembler asm, DataBuilder dataBuilder, FrameContext frameContext,
|
||||
OptionValues options, DebugContext debug, CompilationResult compilationResult, Register nullRegister) {
|
||||
this(codeCache, foreignCalls, frameMap, asm, dataBuilder, frameContext, options, debug, compilationResult, nullRegister, EconomicMap.create(Equivalence.DEFAULT));
|
||||
public CompilationResultBuilder(CodeCacheProvider codeCache,
|
||||
ForeignCallsProvider foreignCalls,
|
||||
FrameMap frameMap,
|
||||
Assembler asm,
|
||||
DataBuilder dataBuilder,
|
||||
FrameContext frameContext,
|
||||
OptionValues options,
|
||||
DebugContext debug,
|
||||
CompilationResult compilationResult,
|
||||
Register uncompressedNullRegister) {
|
||||
this(codeCache,
|
||||
foreignCalls,
|
||||
frameMap,
|
||||
asm,
|
||||
dataBuilder,
|
||||
frameContext,
|
||||
options,
|
||||
debug,
|
||||
compilationResult,
|
||||
uncompressedNullRegister,
|
||||
EconomicMap.create(Equivalence.DEFAULT));
|
||||
}
|
||||
|
||||
public CompilationResultBuilder(CodeCacheProvider codeCache, ForeignCallsProvider foreignCalls, FrameMap frameMap, Assembler asm, DataBuilder dataBuilder, FrameContext frameContext,
|
||||
OptionValues options, DebugContext debug, CompilationResult compilationResult, Register nullRegister, EconomicMap<Constant, Data> dataCache) {
|
||||
public CompilationResultBuilder(CodeCacheProvider codeCache,
|
||||
ForeignCallsProvider foreignCalls,
|
||||
FrameMap frameMap,
|
||||
Assembler asm,
|
||||
DataBuilder dataBuilder,
|
||||
FrameContext frameContext,
|
||||
OptionValues options,
|
||||
DebugContext debug,
|
||||
CompilationResult compilationResult,
|
||||
Register uncompressedNullRegister,
|
||||
EconomicMap<Constant, Data> dataCache) {
|
||||
this.target = codeCache.getTarget();
|
||||
this.codeCache = codeCache;
|
||||
this.foreignCalls = foreignCalls;
|
||||
@ -189,7 +216,7 @@ public class CompilationResultBuilder {
|
||||
this.asm = asm;
|
||||
this.dataBuilder = dataBuilder;
|
||||
this.compilationResult = compilationResult;
|
||||
this.nullRegister = nullRegister;
|
||||
this.uncompressedNullRegister = uncompressedNullRegister;
|
||||
this.frameContext = frameContext;
|
||||
this.options = options;
|
||||
this.debug = debug;
|
||||
|
@ -52,8 +52,8 @@ public interface CompilationResultBuilderFactory {
|
||||
|
||||
@Override
|
||||
public CompilationResultBuilder createBuilder(CodeCacheProvider codeCache, ForeignCallsProvider foreignCalls, FrameMap frameMap, Assembler asm, DataBuilder dataBuilder,
|
||||
FrameContext frameContext, OptionValues options, DebugContext debug, CompilationResult compilationResult, Register nullRegister) {
|
||||
return new CompilationResultBuilder(codeCache, foreignCalls, frameMap, asm, dataBuilder, frameContext, options, debug, compilationResult, nullRegister);
|
||||
FrameContext frameContext, OptionValues options, DebugContext debug, CompilationResult compilationResult, Register uncompressedNullRegister) {
|
||||
return new CompilationResultBuilder(codeCache, foreignCalls, frameMap, asm, dataBuilder, frameContext, options, debug, compilationResult, uncompressedNullRegister);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -60,9 +60,9 @@ import org.graalvm.compiler.lir.StandardOp;
|
||||
import org.graalvm.compiler.lir.StandardOp.BlockEndOp;
|
||||
import org.graalvm.compiler.lir.StandardOp.LabelOp;
|
||||
import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp;
|
||||
import org.graalvm.compiler.lir.hashing.Hasher;
|
||||
import org.graalvm.compiler.lir.SwitchStrategy;
|
||||
import org.graalvm.compiler.lir.Variable;
|
||||
import org.graalvm.compiler.lir.hashing.Hasher;
|
||||
import org.graalvm.compiler.options.Option;
|
||||
import org.graalvm.compiler.options.OptionKey;
|
||||
import org.graalvm.compiler.options.OptionType;
|
||||
@ -229,11 +229,31 @@ public abstract class LIRGenerator implements LIRGeneratorTool {
|
||||
append(moveFactory.createMove(dst, src));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Variable emitReadRegister(Register register, ValueKind<?> kind) {
|
||||
return emitMove(register.asValue(kind));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void emitWriteRegister(Register dst, Value src, ValueKind<?> kind) {
|
||||
emitMove(dst.asValue(kind), src);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void emitMoveConstant(AllocatableValue dst, Constant src) {
|
||||
append(moveFactory.createLoad(dst, src));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canInlineConstant(Constant constant) {
|
||||
return moveFactory.canInlineConstant(constant);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mayEmbedConstantLoad(Constant constant) {
|
||||
return moveFactory.mayEmbedConstantLoad(constant);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value emitConstant(LIRKind kind, Constant constant) {
|
||||
if (moveFactory.canInlineConstant(constant)) {
|
||||
|
@ -64,15 +64,23 @@ public interface LIRGeneratorTool extends DiagnosticLIRGeneratorTool, ValueKindF
|
||||
*/
|
||||
interface MoveFactory {
|
||||
|
||||
/**
|
||||
* Checks whether the loading of the supplied constant can be deferred until usage.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
default boolean mayEmbedConstantLoad(Constant constant) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the supplied constant can be used without loading it into a register for
|
||||
* most operations, i.e., for commonly used arithmetic, logical, and comparison operations.
|
||||
*
|
||||
* @param c The constant to check.
|
||||
* @param constant The constant to check.
|
||||
* @return True if the constant can be used directly, false if the constant needs to be in a
|
||||
* register.
|
||||
*/
|
||||
boolean canInlineConstant(Constant c);
|
||||
boolean canInlineConstant(Constant constant);
|
||||
|
||||
/**
|
||||
* @param constant The constant that might be moved to a stack slot.
|
||||
@ -130,6 +138,10 @@ public interface LIRGeneratorTool extends DiagnosticLIRGeneratorTool, ValueKindF
|
||||
|
||||
BlockScope getBlockScope(AbstractBlockBase<?> block);
|
||||
|
||||
boolean canInlineConstant(Constant constant);
|
||||
|
||||
boolean mayEmbedConstantLoad(Constant constant);
|
||||
|
||||
Value emitConstant(LIRKind kind, Constant constant);
|
||||
|
||||
Value emitJavaConstant(JavaConstant constant);
|
||||
@ -192,6 +204,10 @@ public interface LIRGeneratorTool extends DiagnosticLIRGeneratorTool, ValueKindF
|
||||
|
||||
void emitMove(AllocatableValue dst, Value src);
|
||||
|
||||
Variable emitReadRegister(Register register, ValueKind<?> kind);
|
||||
|
||||
void emitWriteRegister(Register dst, Value src, ValueKind<?> wordStamp);
|
||||
|
||||
void emitMoveConstant(AllocatableValue dst, Constant src);
|
||||
|
||||
Variable emitAddress(AllocatableValue stackslot);
|
||||
|
@ -26,7 +26,7 @@
|
||||
package org.graalvm.compiler.lir.ssa;
|
||||
|
||||
import static jdk.vm.ci.code.ValueUtil.isRegister;
|
||||
import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant;
|
||||
import static org.graalvm.compiler.lir.LIRValueUtil.isConstantValue;
|
||||
import static org.graalvm.compiler.lir.LIRValueUtil.isStackSlotValue;
|
||||
|
||||
import java.util.BitSet;
|
||||
@ -137,7 +137,7 @@ final class SSAVerifier {
|
||||
}
|
||||
|
||||
private static boolean shouldProcess(Value value) {
|
||||
return !value.equals(Value.ILLEGAL) && !isJavaConstant(value) && !isRegister(value) && !isStackSlotValue(value);
|
||||
return !value.equals(Value.ILLEGAL) && !isConstantValue(value) && !isRegister(value) && !isStackSlotValue(value);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -26,7 +26,9 @@ package org.graalvm.compiler.loop.test;
|
||||
|
||||
import java.util.ListIterator;
|
||||
|
||||
import org.graalvm.compiler.api.directives.GraalDirectives;
|
||||
import org.graalvm.compiler.core.common.CompilationIdentifier;
|
||||
import org.graalvm.compiler.core.common.GraalOptions;
|
||||
import org.graalvm.compiler.core.test.GraalCompilerTest;
|
||||
import org.graalvm.compiler.debug.DebugContext;
|
||||
import org.graalvm.compiler.graph.iterators.NodeIterable;
|
||||
@ -216,6 +218,25 @@ public class LoopPartialUnrollTest extends GraalCompilerTest {
|
||||
test("testSignExtensionSnippet", 9L);
|
||||
}
|
||||
|
||||
public static Object objectPhi(int n) {
|
||||
Integer v = Integer.valueOf(200);
|
||||
GraalDirectives.blackhole(v); // Prevents PEA
|
||||
Integer r = 1;
|
||||
|
||||
for (int i = 0; iterationCount(100, i < n); i++) {
|
||||
GraalDirectives.blackhole(r); // Create a phi of two loop invariants
|
||||
r = v;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testObjectPhi() {
|
||||
OptionValues options = new OptionValues(getInitialOptions(), GraalOptions.LoopPeeling, false);
|
||||
test(options, "objectPhi", 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Suites createSuites(OptionValues opts) {
|
||||
Suites suites = super.createSuites(opts).copy();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2019, 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
|
||||
@ -344,7 +344,7 @@ public class LoopEx {
|
||||
}
|
||||
}
|
||||
}
|
||||
LoopFragment.computeNodes(branchNodes, branch.graph(), blocks, exits);
|
||||
LoopFragment.computeNodes(branchNodes, branch.graph(), this, blocks, exits);
|
||||
}
|
||||
|
||||
public EconomicMap<Node, InductionVariable> getInductionVariables() {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2019, 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,12 +25,11 @@
|
||||
package org.graalvm.compiler.loop;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Collections;
|
||||
import java.util.Deque;
|
||||
import java.util.Iterator;
|
||||
|
||||
import jdk.internal.vm.compiler.collections.EconomicMap;
|
||||
import org.graalvm.compiler.debug.GraalError;
|
||||
import org.graalvm.compiler.core.common.cfg.AbstractControlFlowGraph;
|
||||
import org.graalvm.compiler.graph.Graph;
|
||||
import org.graalvm.compiler.graph.Graph.DuplicationReplacement;
|
||||
import org.graalvm.compiler.graph.Node;
|
||||
@ -42,18 +41,15 @@ import org.graalvm.compiler.nodes.EndNode;
|
||||
import org.graalvm.compiler.nodes.FixedNode;
|
||||
import org.graalvm.compiler.nodes.FrameState;
|
||||
import org.graalvm.compiler.nodes.GuardNode;
|
||||
import org.graalvm.compiler.nodes.GuardPhiNode;
|
||||
import org.graalvm.compiler.nodes.GuardProxyNode;
|
||||
import org.graalvm.compiler.nodes.Invoke;
|
||||
import org.graalvm.compiler.nodes.LoopBeginNode;
|
||||
import org.graalvm.compiler.nodes.LoopExitNode;
|
||||
import org.graalvm.compiler.nodes.MergeNode;
|
||||
import org.graalvm.compiler.nodes.NodeView;
|
||||
import org.graalvm.compiler.nodes.PhiNode;
|
||||
import org.graalvm.compiler.nodes.ProxyNode;
|
||||
import org.graalvm.compiler.nodes.StructuredGraph;
|
||||
import org.graalvm.compiler.nodes.ValueNode;
|
||||
import org.graalvm.compiler.nodes.ValuePhiNode;
|
||||
import org.graalvm.compiler.nodes.ValueProxyNode;
|
||||
import org.graalvm.compiler.nodes.VirtualState;
|
||||
import org.graalvm.compiler.nodes.cfg.Block;
|
||||
import org.graalvm.compiler.nodes.cfg.ControlFlowGraph;
|
||||
@ -199,17 +195,7 @@ public abstract class LoopFragment {
|
||||
}
|
||||
}
|
||||
|
||||
protected static NodeBitMap computeNodes(Graph graph, Iterable<AbstractBeginNode> blocks) {
|
||||
return computeNodes(graph, blocks, Collections.emptyList());
|
||||
}
|
||||
|
||||
protected static NodeBitMap computeNodes(Graph graph, Iterable<AbstractBeginNode> blocks, Iterable<AbstractBeginNode> earlyExits) {
|
||||
final NodeBitMap nodes = graph.createNodeBitMap();
|
||||
computeNodes(nodes, graph, blocks, earlyExits);
|
||||
return nodes;
|
||||
}
|
||||
|
||||
protected static void computeNodes(NodeBitMap nodes, Graph graph, Iterable<AbstractBeginNode> blocks, Iterable<AbstractBeginNode> earlyExits) {
|
||||
protected static void computeNodes(NodeBitMap nodes, Graph graph, LoopEx loop, Iterable<AbstractBeginNode> blocks, Iterable<AbstractBeginNode> earlyExits) {
|
||||
for (AbstractBeginNode b : blocks) {
|
||||
if (b.isDeleted()) {
|
||||
continue;
|
||||
@ -261,11 +247,11 @@ public abstract class LoopFragment {
|
||||
for (Node n : b.getBlockNodes()) {
|
||||
if (n instanceof CommitAllocationNode) {
|
||||
for (VirtualObjectNode obj : ((CommitAllocationNode) n).getVirtualObjects()) {
|
||||
markFloating(worklist, obj, nodes, nonLoopNodes);
|
||||
markFloating(worklist, loop, obj, nodes, nonLoopNodes);
|
||||
}
|
||||
}
|
||||
if (n instanceof MonitorEnterNode) {
|
||||
markFloating(worklist, ((MonitorEnterNode) n).getMonitorId(), nodes, nonLoopNodes);
|
||||
markFloating(worklist, loop, ((MonitorEnterNode) n).getMonitorId(), nodes, nonLoopNodes);
|
||||
}
|
||||
if (n instanceof AbstractMergeNode) {
|
||||
/*
|
||||
@ -274,12 +260,12 @@ public abstract class LoopFragment {
|
||||
*/
|
||||
for (PhiNode phi : ((AbstractMergeNode) n).phis()) {
|
||||
for (Node usage : phi.usages()) {
|
||||
markFloating(worklist, usage, nodes, nonLoopNodes);
|
||||
markFloating(worklist, loop, usage, nodes, nonLoopNodes);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (Node usage : n.usages()) {
|
||||
markFloating(worklist, usage, nodes, nonLoopNodes);
|
||||
markFloating(worklist, loop, usage, nodes, nonLoopNodes);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -331,10 +317,14 @@ public abstract class LoopFragment {
|
||||
workList.push(entry);
|
||||
}
|
||||
|
||||
private static void markFloating(Deque<WorkListEntry> workList, Node start, NodeBitMap loopNodes, NodeBitMap nonLoopNodes) {
|
||||
private static void markFloating(Deque<WorkListEntry> workList, LoopEx loop, Node start, NodeBitMap loopNodes, NodeBitMap nonLoopNodes) {
|
||||
if (isLoopNode(start, loopNodes, nonLoopNodes).isKnown()) {
|
||||
return;
|
||||
}
|
||||
|
||||
LoopBeginNode loopBeginNode = loop.loopBegin();
|
||||
ControlFlowGraph cfg = loop.loopsData().getCFG();
|
||||
|
||||
pushWorkList(workList, start, loopNodes);
|
||||
while (!workList.isEmpty()) {
|
||||
WorkListEntry currentEntry = workList.peek();
|
||||
@ -352,13 +342,27 @@ public abstract class LoopFragment {
|
||||
workList.pop();
|
||||
boolean isLoopNode = currentEntry.isLoopNode;
|
||||
Node current = currentEntry.n;
|
||||
if (!isLoopNode && current instanceof GuardNode) {
|
||||
/*
|
||||
* (gd) this is only OK if we are not going to make loop transforms based on
|
||||
* this
|
||||
*/
|
||||
assert !((GuardNode) current).graph().hasValueProxies();
|
||||
isLoopNode = true;
|
||||
if (!isLoopNode && current instanceof GuardNode && !current.hasUsages()) {
|
||||
GuardNode guard = (GuardNode) current;
|
||||
if (isLoopNode(guard.getCondition(), loopNodes, nonLoopNodes) != TriState.FALSE) {
|
||||
ValueNode anchor = guard.getAnchor().asNode();
|
||||
TriState isAnchorInLoop = isLoopNode(anchor, loopNodes, nonLoopNodes);
|
||||
if (isAnchorInLoop != TriState.FALSE) {
|
||||
if (!(anchor instanceof LoopExitNode && ((LoopExitNode) anchor).loopBegin() == loopBeginNode)) {
|
||||
/*
|
||||
* (gd) this is wrong in general, it's completely avoidable while we
|
||||
* are doing loop transforms using ValueProxies. If it happens after
|
||||
* it could still cause problem.
|
||||
*/
|
||||
assert !((GuardNode) current).graph().hasValueProxies();
|
||||
isLoopNode = true;
|
||||
}
|
||||
} else if (AbstractControlFlowGraph.strictlyDominates(cfg.blockFor(anchor), cfg.blockFor(loopBeginNode))) {
|
||||
// The anchor is above the loop. The no-usage guard can potentially be
|
||||
// scheduled inside the loop.
|
||||
isLoopNode = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isLoopNode) {
|
||||
loopNodes.mark(current);
|
||||
@ -467,14 +471,7 @@ public abstract class LoopFragment {
|
||||
final ValueNode replaceWith;
|
||||
ValueNode newVpn = prim(newEarlyExitIsLoopExit ? vpn : vpn.value());
|
||||
if (newVpn != null) {
|
||||
PhiNode phi;
|
||||
if (vpn instanceof ValueProxyNode) {
|
||||
phi = graph.addWithoutUnique(new ValuePhiNode(vpn.stamp(NodeView.DEFAULT), merge));
|
||||
} else if (vpn instanceof GuardProxyNode) {
|
||||
phi = graph.addWithoutUnique(new GuardPhiNode(merge));
|
||||
} else {
|
||||
throw GraalError.shouldNotReachHere();
|
||||
}
|
||||
PhiNode phi = vpn.createPhi(merge);
|
||||
phi.addInput(vpn);
|
||||
phi.addInput(newVpn);
|
||||
replaceWith = phi;
|
||||
|
@ -169,12 +169,13 @@ public class LoopFragmentInside extends LoopFragment {
|
||||
LoopBeginNode mainLoopBegin = loop.loopBegin();
|
||||
ArrayList<ValueNode> backedgeValues = new ArrayList<>();
|
||||
for (PhiNode mainPhiNode : mainLoopBegin.phis()) {
|
||||
ValueNode duplicatedNode = getDuplicatedNode(mainPhiNode.valueAt(1));
|
||||
ValueNode originalNode = mainPhiNode.valueAt(1);
|
||||
ValueNode duplicatedNode = getDuplicatedNode(originalNode);
|
||||
if (duplicatedNode == null) {
|
||||
if (mainLoopBegin.isPhiAtMerge(mainPhiNode.valueAt(1))) {
|
||||
duplicatedNode = ((PhiNode) (mainPhiNode.valueAt(1))).valueAt(1);
|
||||
if (mainLoopBegin.isPhiAtMerge(originalNode)) {
|
||||
duplicatedNode = ((PhiNode) (originalNode)).valueAt(1);
|
||||
} else {
|
||||
assert mainPhiNode.valueAt(1).isConstant() : mainPhiNode.valueAt(1);
|
||||
assert originalNode.isConstant() || loop.isOutsideLoop(originalNode) : "Not duplicated node " + originalNode;
|
||||
}
|
||||
}
|
||||
backedgeValues.add(duplicatedNode);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2019, 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
|
||||
@ -64,7 +64,9 @@ public class LoopFragmentWhole extends LoopFragment {
|
||||
public NodeBitMap nodes() {
|
||||
if (nodes == null) {
|
||||
Loop<Block> loop = loop().loop();
|
||||
nodes = LoopFragment.computeNodes(graph(), LoopFragment.toHirBlocks(loop.getBlocks()), LoopFragment.toHirBlocks(loop.getLoopExits()));
|
||||
NodeBitMap loopNodes = graph().createNodeBitMap();
|
||||
LoopFragment.computeNodes(loopNodes, graph(), loop(), LoopFragment.toHirBlocks(loop.getBlocks()), LoopFragment.toHirBlocks(loop.getLoopExits()));
|
||||
nodes = loopNodes;
|
||||
}
|
||||
return nodes;
|
||||
}
|
||||
@ -110,7 +112,6 @@ public class LoopFragmentWhole extends LoopFragment {
|
||||
|
||||
@Override
|
||||
public void insertBefore(LoopEx loop) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
// nothing to do
|
||||
}
|
||||
}
|
||||
|
@ -59,21 +59,20 @@ public abstract class AbstractBeginNode extends FixedWithNextNode implements LIR
|
||||
Node next = from;
|
||||
while (next != null) {
|
||||
if (next instanceof AbstractBeginNode) {
|
||||
AbstractBeginNode begin = (AbstractBeginNode) next;
|
||||
return begin;
|
||||
return (AbstractBeginNode) next;
|
||||
}
|
||||
next = next.predecessor();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void evacuateGuards(FixedNode evacuateFrom) {
|
||||
private void evacuateAnchored(FixedNode evacuateFrom) {
|
||||
if (!hasNoUsages()) {
|
||||
AbstractBeginNode prevBegin = prevBegin(evacuateFrom);
|
||||
assert prevBegin != null;
|
||||
for (Node anchored : anchored().snapshot()) {
|
||||
anchored.replaceFirstInput(this, prevBegin);
|
||||
}
|
||||
replaceAtUsages(InputType.Anchor, prevBegin);
|
||||
replaceAtUsages(InputType.Guard, prevBegin);
|
||||
assert anchored().isEmpty() : anchored().snapshot();
|
||||
}
|
||||
}
|
||||
|
||||
@ -82,7 +81,7 @@ public abstract class AbstractBeginNode extends FixedWithNextNode implements LIR
|
||||
}
|
||||
|
||||
public void prepareDelete(FixedNode evacuateFrom) {
|
||||
evacuateGuards(evacuateFrom);
|
||||
evacuateAnchored(evacuateFrom);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2009, 2019, 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
|
||||
@ -38,11 +38,14 @@ import org.graalvm.compiler.core.common.type.StampFactory;
|
||||
import org.graalvm.compiler.debug.GraalError;
|
||||
import org.graalvm.compiler.graph.Node;
|
||||
import org.graalvm.compiler.graph.NodeClass;
|
||||
import org.graalvm.compiler.graph.NodeMap;
|
||||
import org.graalvm.compiler.graph.iterators.NodeIterable;
|
||||
import org.graalvm.compiler.lir.ConstantValue;
|
||||
import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
|
||||
import org.graalvm.compiler.nodeinfo.NodeInfo;
|
||||
import org.graalvm.compiler.nodeinfo.Verbosity;
|
||||
import org.graalvm.compiler.nodes.calc.FloatingNode;
|
||||
import org.graalvm.compiler.nodes.cfg.Block;
|
||||
import org.graalvm.compiler.nodes.spi.ArrayLengthProvider;
|
||||
import org.graalvm.compiler.nodes.spi.LIRLowerable;
|
||||
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
|
||||
@ -143,14 +146,32 @@ public final class ConstantNode extends FloatingNode implements LIRLowerable, Ar
|
||||
|
||||
@Override
|
||||
public void generate(NodeLIRBuilderTool gen) {
|
||||
LIRKind kind = gen.getLIRGeneratorTool().getLIRKind(stamp(NodeView.DEFAULT));
|
||||
LIRGeneratorTool lirTool = gen.getLIRGeneratorTool();
|
||||
LIRKind kind = lirTool.getLIRKind(stamp(NodeView.DEFAULT));
|
||||
if (onlyUsedInVirtualState()) {
|
||||
gen.setResult(this, new ConstantValue(kind, value));
|
||||
} else if (lirTool.canInlineConstant(value) || (lirTool.mayEmbedConstantLoad(value) && hasExactlyOneUsage() && onlyUsedInCurrentBlock())) {
|
||||
gen.setResult(this, new ConstantValue(lirTool.toRegisterKind(kind), value));
|
||||
} else {
|
||||
gen.setResult(this, gen.getLIRGeneratorTool().emitConstant(kind, value));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Expecting false for loop invariant.
|
||||
*/
|
||||
private boolean onlyUsedInCurrentBlock() {
|
||||
assert graph().getLastSchedule() != null;
|
||||
NodeMap<Block> nodeBlockMap = graph().getLastSchedule().getNodeToBlockMap();
|
||||
Block currentBlock = nodeBlockMap.get(this);
|
||||
for (Node usage : usages()) {
|
||||
if (currentBlock != nodeBlockMap.get(usage)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean onlyUsedInVirtualState() {
|
||||
for (Node n : this.usages()) {
|
||||
if (n instanceof VirtualState) {
|
||||
|
@ -30,7 +30,9 @@ import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_0;
|
||||
|
||||
import org.graalvm.compiler.debug.GraalError;
|
||||
import org.graalvm.compiler.graph.IterableNodeType;
|
||||
import org.graalvm.compiler.graph.Node;
|
||||
import org.graalvm.compiler.graph.NodeClass;
|
||||
import org.graalvm.compiler.graph.iterators.NodeIterable;
|
||||
import org.graalvm.compiler.nodeinfo.NodeInfo;
|
||||
import org.graalvm.compiler.nodes.spi.LIRLowerable;
|
||||
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
|
||||
@ -51,4 +53,24 @@ public final class EntryMarkerNode extends BeginStateSplitNode implements Iterab
|
||||
public void generate(NodeLIRBuilderTool gen) {
|
||||
throw new GraalError("OnStackReplacementNode should not survive");
|
||||
}
|
||||
|
||||
@Override
|
||||
public NodeIterable<Node> anchored() {
|
||||
return super.anchored().filter(n -> {
|
||||
if (n instanceof EntryProxyNode) {
|
||||
EntryProxyNode proxyNode = (EntryProxyNode) n;
|
||||
return proxyNode.proxyPoint != this;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareDelete(FixedNode evacuateFrom) {
|
||||
for (Node usage : usages().filter(EntryProxyNode.class).snapshot()) {
|
||||
EntryProxyNode proxy = (EntryProxyNode) usage;
|
||||
proxy.replaceAndDelete(proxy.value());
|
||||
}
|
||||
super.prepareDelete(evacuateFrom);
|
||||
}
|
||||
}
|
||||
|
@ -30,19 +30,22 @@ import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_2;
|
||||
|
||||
import org.graalvm.compiler.debug.DebugCloseable;
|
||||
import org.graalvm.compiler.graph.IterableNodeType;
|
||||
import org.graalvm.compiler.graph.Node;
|
||||
import org.graalvm.compiler.graph.NodeClass;
|
||||
import org.graalvm.compiler.graph.NodeSourcePosition;
|
||||
import org.graalvm.compiler.graph.spi.SimplifierTool;
|
||||
import org.graalvm.compiler.nodeinfo.NodeInfo;
|
||||
import org.graalvm.compiler.nodes.calc.IntegerEqualsNode;
|
||||
import org.graalvm.compiler.nodes.spi.Lowerable;
|
||||
import org.graalvm.compiler.nodes.spi.LoweringTool;
|
||||
import org.graalvm.compiler.nodes.spi.SwitchFoldable;
|
||||
|
||||
import jdk.vm.ci.meta.DeoptimizationAction;
|
||||
import jdk.vm.ci.meta.DeoptimizationReason;
|
||||
import jdk.vm.ci.meta.SpeculationLog;
|
||||
|
||||
@NodeInfo(nameTemplate = "FixedGuard(!={p#negated}) {p#reason/s}", allowedUsageTypes = Guard, size = SIZE_2, cycles = CYCLES_2)
|
||||
public final class FixedGuardNode extends AbstractFixedGuardNode implements Lowerable, IterableNodeType {
|
||||
public final class FixedGuardNode extends AbstractFixedGuardNode implements Lowerable, IterableNodeType, SwitchFoldable {
|
||||
public static final NodeClass<FixedGuardNode> TYPE = NodeClass.create(FixedGuardNode.class);
|
||||
|
||||
public FixedGuardNode(LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action) {
|
||||
@ -115,4 +118,92 @@ public final class FixedGuardNode extends AbstractFixedGuardNode implements Lowe
|
||||
public boolean canDeoptimize() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node getNextSwitchFoldableBranch() {
|
||||
return next();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInSwitch(ValueNode switchValue) {
|
||||
return hasNoUsages() && isNegated() && SwitchFoldable.maybeIsInSwitch(condition()) && SwitchFoldable.sameSwitchValue(condition(), switchValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cutOffCascadeNode() {
|
||||
/* nop */
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cutOffLowestCascadeNode() {
|
||||
setNext(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDefaultSuccessor(AbstractBeginNode beginNode) {
|
||||
return beginNode.next() == next();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractBeginNode getDefault() {
|
||||
FixedNode defaultNode = next();
|
||||
setNext(null);
|
||||
return BeginNode.begin(defaultNode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueNode switchValue() {
|
||||
if (SwitchFoldable.maybeIsInSwitch(condition())) {
|
||||
return ((IntegerEqualsNode) condition()).getX();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNonInitializedProfile() {
|
||||
// @formatter:off
|
||||
// Checkstyle: stop
|
||||
/*
|
||||
* These nodes can appear in non initialized cascades. Though they are technically profiled
|
||||
* nodes, their presence does not really prevent us from constructing a uniform distribution
|
||||
* for the new switch, while keeping these to probability 0. Furthermore, these can be the
|
||||
* result of the pattern:
|
||||
* if (c) {
|
||||
* CompilerDirectives.transferToInterpreter();
|
||||
* }
|
||||
* Since we cannot differentiate this case from, say, a guard created because profiling
|
||||
* determined that the branch was never taken, and given what we saw before, we will
|
||||
* consider all fixedGuards as nodes with no profiles for switch folding purposes.
|
||||
*/
|
||||
// Checkstyle: resume
|
||||
// @formatter:on
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int intKeyAt(int i) {
|
||||
assert i == 0;
|
||||
return ((IntegerEqualsNode) condition()).getY().asJavaConstant().asInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public double keyProbability(int i) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractBeginNode keySuccessor(int i) {
|
||||
DeoptimizeNode deopt = new DeoptimizeNode(getAction(), getReason(), getSpeculation());
|
||||
deopt.setNodeSourcePosition(getNodeSourcePosition());
|
||||
AbstractBeginNode begin = new BeginNode();
|
||||
// Link the two nodes, but do not add them to the graph yet, so we do not need to remove
|
||||
// them on an abort.
|
||||
begin.next = deopt;
|
||||
return begin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double defaultProbability() {
|
||||
return 1.0d;
|
||||
}
|
||||
}
|
||||
|
@ -319,7 +319,7 @@ public class GraphDecoder {
|
||||
public static final NodeClass<ProxyPlaceholder> TYPE = NodeClass.create(ProxyPlaceholder.class);
|
||||
|
||||
@Input ValueNode value;
|
||||
@Input(InputType.Unchecked) Node proxyPoint;
|
||||
@Input(InputType.Association) Node proxyPoint;
|
||||
|
||||
public ProxyPlaceholder(ValueNode value, MergeNode proxyPoint) {
|
||||
super(TYPE, value.stamp(NodeView.DEFAULT));
|
||||
@ -884,14 +884,7 @@ public class GraphDecoder {
|
||||
|
||||
if (!merge.isPhiAtMerge(existing)) {
|
||||
/* Now we have two different values, so we need to create a phi node. */
|
||||
PhiNode phi;
|
||||
if (proxy instanceof ValueProxyNode) {
|
||||
phi = graph.addWithoutUnique(new ValuePhiNode(proxy.stamp(NodeView.DEFAULT), merge));
|
||||
} else if (proxy instanceof GuardProxyNode) {
|
||||
phi = graph.addWithoutUnique(new GuardPhiNode(merge));
|
||||
} else {
|
||||
throw GraalError.shouldNotReachHere();
|
||||
}
|
||||
PhiNode phi = proxy.createPhi(merge);
|
||||
/* Add the inputs from all previous exits. */
|
||||
for (int j = 0; j < merge.phiPredecessorCount() - 1; j++) {
|
||||
phi.addInput(existing);
|
||||
@ -1336,6 +1329,11 @@ public class GraphDecoder {
|
||||
* @param methodScope The current method.
|
||||
*/
|
||||
protected void cleanupGraph(MethodScope methodScope) {
|
||||
for (MergeNode merge : graph.getNodes(MergeNode.TYPE)) {
|
||||
for (ProxyPlaceholder placeholder : merge.usages().filter(ProxyPlaceholder.class).snapshot()) {
|
||||
placeholder.replaceAndDelete(placeholder.value);
|
||||
}
|
||||
}
|
||||
assert verifyEdges();
|
||||
}
|
||||
|
||||
|
@ -61,6 +61,11 @@ public final class GuardProxyNode extends ProxyNode implements GuardingNode, Pro
|
||||
return (value == null ? null : value.asNode());
|
||||
}
|
||||
|
||||
@Override
|
||||
public PhiNode createPhi(AbstractMergeNode merge) {
|
||||
return graph().addWithoutUnique(new GuardPhiNode(merge));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node getOriginalNode() {
|
||||
return (value == null ? null : value.asNode());
|
||||
|
@ -42,6 +42,7 @@ import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecode;
|
||||
import org.graalvm.compiler.core.common.calc.Condition;
|
||||
import org.graalvm.compiler.core.common.type.FloatStamp;
|
||||
import org.graalvm.compiler.core.common.type.IntegerStamp;
|
||||
import org.graalvm.compiler.core.common.type.PrimitiveStamp;
|
||||
import org.graalvm.compiler.core.common.type.Stamp;
|
||||
import org.graalvm.compiler.core.common.type.StampFactory;
|
||||
import org.graalvm.compiler.debug.CounterKey;
|
||||
@ -71,8 +72,10 @@ import org.graalvm.compiler.nodes.java.InstanceOfNode;
|
||||
import org.graalvm.compiler.nodes.java.LoadFieldNode;
|
||||
import org.graalvm.compiler.nodes.spi.LIRLowerable;
|
||||
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
|
||||
import org.graalvm.compiler.nodes.spi.SwitchFoldable;
|
||||
import org.graalvm.compiler.nodes.util.GraphUtil;
|
||||
|
||||
import jdk.vm.ci.code.CodeUtil;
|
||||
import jdk.vm.ci.meta.Constant;
|
||||
import jdk.vm.ci.meta.JavaConstant;
|
||||
import jdk.vm.ci.meta.JavaKind;
|
||||
@ -87,7 +90,7 @@ import jdk.vm.ci.meta.TriState;
|
||||
* of a comparison.
|
||||
*/
|
||||
@NodeInfo(cycles = CYCLES_1, size = SIZE_2, sizeRationale = "2 jmps")
|
||||
public final class IfNode extends ControlSplitNode implements Simplifiable, LIRLowerable {
|
||||
public final class IfNode extends ControlSplitNode implements Simplifiable, LIRLowerable, SwitchFoldable {
|
||||
public static final NodeClass<IfNode> TYPE = NodeClass.create(IfNode.class);
|
||||
|
||||
private static final CounterKey CORRECTED_PROBABILITIES = DebugContext.counter("CorrectedProbabilities");
|
||||
@ -297,6 +300,10 @@ public final class IfNode extends ControlSplitNode implements Simplifiable, LIRL
|
||||
return;
|
||||
}
|
||||
|
||||
if (switchTransformationOptimization(tool)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (falseSuccessor().hasNoUsages() && (!(falseSuccessor() instanceof LoopExitNode)) && falseSuccessor().next() instanceof IfNode &&
|
||||
!(((IfNode) falseSuccessor().next()).falseSuccessor() instanceof LoopExitNode)) {
|
||||
AbstractBeginNode intermediateBegin = falseSuccessor();
|
||||
@ -454,6 +461,70 @@ public final class IfNode extends ControlSplitNode implements Simplifiable, LIRL
|
||||
return true;
|
||||
}
|
||||
|
||||
// SwitchFoldable implementation.
|
||||
|
||||
@Override
|
||||
public Node getNextSwitchFoldableBranch() {
|
||||
return falseSuccessor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInSwitch(ValueNode switchValue) {
|
||||
return SwitchFoldable.maybeIsInSwitch(condition()) && SwitchFoldable.sameSwitchValue(condition(), switchValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cutOffCascadeNode() {
|
||||
setTrueSuccessor(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cutOffLowestCascadeNode() {
|
||||
setFalseSuccessor(null);
|
||||
setTrueSuccessor(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractBeginNode getDefault() {
|
||||
return falseSuccessor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueNode switchValue() {
|
||||
if (SwitchFoldable.maybeIsInSwitch(condition())) {
|
||||
return ((IntegerEqualsNode) condition()).getX();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNonInitializedProfile() {
|
||||
return getTrueSuccessorProbability() == 0.5d;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int intKeyAt(int i) {
|
||||
assert i == 0;
|
||||
return ((IntegerEqualsNode) condition()).getY().asJavaConstant().asInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public double keyProbability(int i) {
|
||||
assert i == 0;
|
||||
return getTrueSuccessorProbability();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractBeginNode keySuccessor(int i) {
|
||||
assert i == 0;
|
||||
return trueSuccessor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public double defaultProbability() {
|
||||
return 1.0d - getTrueSuccessorProbability();
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to optimize this as if it were a {@link ConditionalNode}.
|
||||
*/
|
||||
@ -606,6 +677,50 @@ public final class IfNode extends ControlSplitNode implements Simplifiable, LIRL
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (y instanceof PrimitiveConstant && ((PrimitiveConstant) y).asLong() < 0 && falseSuccessor().next() instanceof IfNode) {
|
||||
IfNode ifNode2 = (IfNode) falseSuccessor().next();
|
||||
AbstractBeginNode falseSucc = ifNode2.falseSuccessor();
|
||||
AbstractBeginNode trueSucc = ifNode2.trueSuccessor();
|
||||
IntegerBelowNode below = null;
|
||||
if (ifNode2.condition() instanceof IntegerLessThanNode) {
|
||||
ValueNode x = lessThan.getX();
|
||||
IntegerLessThanNode lessThan2 = (IntegerLessThanNode) ifNode2.condition();
|
||||
/*
|
||||
* Convert x >= -C1 && x < C2, represented as !(x < -C1) && x < C2, into an
|
||||
* unsigned compare. This condition is equivalent to x + C1 |<| C1 + C2 if C1 +
|
||||
* C2 does not overflow.
|
||||
*/
|
||||
Constant c2 = lessThan2.getY().stamp(view).asConstant();
|
||||
if (lessThan2.getX() == x && c2 instanceof PrimitiveConstant && ((PrimitiveConstant) c2).asLong() > 0 &&
|
||||
x.stamp(view).isCompatible(lessThan.getY().stamp(view)) &&
|
||||
x.stamp(view).isCompatible(lessThan2.getY().stamp(view)) &&
|
||||
sameDestination(trueSuccessor(), ifNode2.falseSuccessor)) {
|
||||
long newLimitValue = -((PrimitiveConstant) y).asLong() + ((PrimitiveConstant) c2).asLong();
|
||||
// Make sure the limit fits into the target type without overflow.
|
||||
if (newLimitValue > 0 && newLimitValue <= CodeUtil.maxValue(PrimitiveStamp.getBits(x.stamp(view)))) {
|
||||
ConstantNode newLimit = ConstantNode.forIntegerStamp(x.stamp(view), newLimitValue, graph());
|
||||
ConstantNode c1 = ConstantNode.forIntegerStamp(x.stamp(view), -((PrimitiveConstant) y).asLong(), graph());
|
||||
ValueNode addNode = graph().addOrUniqueWithInputs(AddNode.create(x, c1, view));
|
||||
below = graph().unique(new IntegerBelowNode(addNode, newLimit));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (below != null) {
|
||||
try (DebugCloseable position = ifNode2.withNodeSourcePosition()) {
|
||||
ifNode2.setTrueSuccessor(null);
|
||||
ifNode2.setFalseSuccessor(null);
|
||||
|
||||
IfNode newIfNode = graph().add(new IfNode(below, trueSucc, falseSucc, trueSuccessorProbability));
|
||||
// Remove the < -C1 test.
|
||||
tool.deleteBranch(trueSuccessor);
|
||||
graph().removeSplit(this, falseSuccessor);
|
||||
|
||||
// Replace the second test with the new one.
|
||||
ifNode2.predecessor().replaceFirstSuccessor(ifNode2, newIfNode);
|
||||
ifNode2.safeDelete();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@ -1268,8 +1383,7 @@ public final class IfNode extends ControlSplitNode implements Simplifiable, LIRL
|
||||
private MergeNode insertMerge(AbstractBeginNode begin, FrameState stateAfter) {
|
||||
MergeNode merge = graph().add(new MergeNode());
|
||||
if (!begin.anchored().isEmpty()) {
|
||||
Object before = null;
|
||||
before = begin.anchored().snapshot();
|
||||
Object before = begin.anchored().snapshot();
|
||||
begin.replaceAtUsages(InputType.Guard, merge);
|
||||
begin.replaceAtUsages(InputType.Anchor, merge);
|
||||
assert begin.anchored().isEmpty() : before + " " + begin.anchored().snapshot();
|
||||
|
@ -75,4 +75,6 @@ public abstract class ProxyNode extends FloatingNode implements ValueNumberable
|
||||
public static GuardProxyNode forGuard(GuardingNode value, LoopExitNode exit, StructuredGraph graph) {
|
||||
return graph.unique(new GuardProxyNode(value, exit));
|
||||
}
|
||||
|
||||
public abstract PhiNode createPhi(AbstractMergeNode merge);
|
||||
}
|
||||
|
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