8231973: Update Graal
Reviewed-by: kvn
This commit is contained in:
parent
2918f86d2b
commit
183e2e119d
@ -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.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -36,6 +36,7 @@ import javax.management.NotCompliantMBeanException;
|
||||
import javax.management.ObjectName;
|
||||
|
||||
import org.graalvm.compiler.debug.TTY;
|
||||
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
|
||||
import org.graalvm.compiler.hotspot.HotSpotGraalManagementRegistration;
|
||||
import org.graalvm.compiler.hotspot.HotSpotGraalRuntime;
|
||||
import org.graalvm.compiler.serviceprovider.ServiceProvider;
|
||||
@ -56,7 +57,7 @@ public final class HotSpotGraalManagement implements HotSpotGraalManagementRegis
|
||||
HotSpotGraalManagement nextDeferred;
|
||||
|
||||
@Override
|
||||
public void initialize(HotSpotGraalRuntime runtime) {
|
||||
public void initialize(HotSpotGraalRuntime runtime, GraalHotSpotVMConfig config) {
|
||||
if (bean == null) {
|
||||
if (runtime.getManagement() != this) {
|
||||
throw new IllegalArgumentException("Cannot initialize a second management object for runtime " + runtime.getName());
|
||||
|
@ -57,7 +57,7 @@ import jdk.vm.ci.services.Services;
|
||||
/**
|
||||
* MBean used to access properties and operations of a {@link HotSpotGraalRuntime} instance.
|
||||
*/
|
||||
final class HotSpotGraalRuntimeMBean implements DynamicMBean {
|
||||
public final class HotSpotGraalRuntimeMBean implements DynamicMBean {
|
||||
|
||||
/**
|
||||
* The runtime instance to which this bean provides a management connection.
|
||||
@ -69,16 +69,16 @@ final class HotSpotGraalRuntimeMBean implements DynamicMBean {
|
||||
*/
|
||||
private final ObjectName objectName;
|
||||
|
||||
HotSpotGraalRuntimeMBean(ObjectName objectName, HotSpotGraalRuntime runtime) {
|
||||
public HotSpotGraalRuntimeMBean(ObjectName objectName, HotSpotGraalRuntime runtime) {
|
||||
this.objectName = objectName;
|
||||
this.runtime = runtime;
|
||||
}
|
||||
|
||||
ObjectName getObjectName() {
|
||||
public ObjectName getObjectName() {
|
||||
return objectName;
|
||||
}
|
||||
|
||||
HotSpotGraalRuntime getRuntime() {
|
||||
public HotSpotGraalRuntime getRuntime() {
|
||||
return runtime;
|
||||
}
|
||||
|
||||
|
@ -1,69 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 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.management;
|
||||
|
||||
import static java.lang.Thread.currentThread;
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.util.List;
|
||||
|
||||
import org.graalvm.compiler.serviceprovider.ServiceProvider;
|
||||
import org.graalvm.compiler.serviceprovider.JMXService;
|
||||
|
||||
import com.sun.management.ThreadMXBean;
|
||||
|
||||
/**
|
||||
* Implementation of {@link JMXService} for JDK 13 and later.
|
||||
*/
|
||||
@ServiceProvider(JMXService.class)
|
||||
public class JMXServiceProvider extends JMXService {
|
||||
private final ThreadMXBean threadMXBean = (ThreadMXBean) ManagementFactory.getThreadMXBean();
|
||||
|
||||
@Override
|
||||
protected long getThreadAllocatedBytes(long id) {
|
||||
return threadMXBean.getThreadAllocatedBytes(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected long getCurrentThreadCpuTime() {
|
||||
long[] times = threadMXBean.getThreadCpuTime(new long[]{currentThread().getId()});
|
||||
return times[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isThreadAllocatedMemorySupported() {
|
||||
return threadMXBean.isThreadAllocatedMemorySupported();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isCurrentThreadCpuTimeSupported() {
|
||||
return threadMXBean.isThreadCpuTimeSupported();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<String> getInputArguments() {
|
||||
return ManagementFactory.getRuntimeMXBean().getInputArguments();
|
||||
}
|
||||
}
|
@ -29,7 +29,7 @@ import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@ -122,7 +122,7 @@ public final class OptionsEncoder {
|
||||
* @throws IllegalArgumentException if {@code input} cannot be decoded
|
||||
*/
|
||||
public static Map<String, Object> decode(byte[] input) {
|
||||
Map<String, Object> res = new HashMap<>();
|
||||
Map<String, Object> res = new LinkedHashMap<>();
|
||||
try (DataInputStream in = new DataInputStream(new ByteArrayInputStream(input))) {
|
||||
final int size = in.readInt();
|
||||
for (int i = 0; i < size; i++) {
|
||||
|
@ -25,6 +25,11 @@
|
||||
|
||||
package org.graalvm.compiler.asm.aarch64;
|
||||
|
||||
import static jdk.vm.ci.aarch64.AArch64.CPU;
|
||||
import static jdk.vm.ci.aarch64.AArch64.rscratch1;
|
||||
import static jdk.vm.ci.aarch64.AArch64.rscratch2;
|
||||
import static jdk.vm.ci.aarch64.AArch64.sp;
|
||||
import static jdk.vm.ci.aarch64.AArch64.zr;
|
||||
import static org.graalvm.compiler.asm.aarch64.AArch64Address.AddressingMode.BASE_REGISTER_ONLY;
|
||||
import static org.graalvm.compiler.asm.aarch64.AArch64Address.AddressingMode.EXTENDED_REGISTER_OFFSET;
|
||||
import static org.graalvm.compiler.asm.aarch64.AArch64Address.AddressingMode.IMMEDIATE_SCALED;
|
||||
@ -35,13 +40,6 @@ import static org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler.AddressGene
|
||||
import static org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler.AddressGenerationPlan.WorkPlan.NO_WORK;
|
||||
|
||||
import org.graalvm.compiler.asm.BranchTargetOutOfBoundsException;
|
||||
|
||||
import static jdk.vm.ci.aarch64.AArch64.CPU;
|
||||
import static jdk.vm.ci.aarch64.AArch64.r8;
|
||||
import static jdk.vm.ci.aarch64.AArch64.r9;
|
||||
import static jdk.vm.ci.aarch64.AArch64.sp;
|
||||
import static jdk.vm.ci.aarch64.AArch64.zr;
|
||||
|
||||
import org.graalvm.compiler.asm.Label;
|
||||
import org.graalvm.compiler.core.common.NumUtil;
|
||||
import org.graalvm.compiler.debug.GraalError;
|
||||
@ -52,7 +50,7 @@ import jdk.vm.ci.code.TargetDescription;
|
||||
|
||||
public class AArch64MacroAssembler extends AArch64Assembler {
|
||||
|
||||
private final ScratchRegister[] scratchRegister = new ScratchRegister[]{new ScratchRegister(r8), new ScratchRegister(r9)};
|
||||
private final ScratchRegister[] scratchRegister = new ScratchRegister[]{new ScratchRegister(rscratch1), new ScratchRegister(rscratch2)};
|
||||
|
||||
// Points to the next free scratch register
|
||||
private int nextFreeScratchRegister = 0;
|
||||
@ -1310,6 +1308,20 @@ public class AArch64MacroAssembler extends AArch64Assembler {
|
||||
super.fmsub(size, dst, dst, d, n);
|
||||
}
|
||||
|
||||
/**
|
||||
* dst = src1 * src2 + src3.
|
||||
*
|
||||
* @param size register size.
|
||||
* @param dst floating point register. May not be null.
|
||||
* @param src1 floating point register. May not be null.
|
||||
* @param src2 floating point register. May not be null.
|
||||
* @param src3 floating point register. May not be null.
|
||||
*/
|
||||
@Override
|
||||
public void fmadd(int size, Register dst, Register src1, Register src2, Register src3) {
|
||||
super.fmadd(size, dst, src1, src2, src3);
|
||||
}
|
||||
|
||||
/* Branches */
|
||||
|
||||
/**
|
||||
@ -1367,32 +1379,32 @@ public class AArch64MacroAssembler extends AArch64Assembler {
|
||||
case 64: {
|
||||
// Be careful with registers: it's possible that x, y, and dst are the same
|
||||
// register.
|
||||
Register rscratch1 = sc1.getRegister();
|
||||
Register rscratch2 = sc2.getRegister();
|
||||
mul(64, rscratch1, x, y); // Result bits 0..63
|
||||
smulh(64, rscratch2, x, y); // Result bits 64..127
|
||||
Register temp1 = sc1.getRegister();
|
||||
Register temp2 = sc2.getRegister();
|
||||
mul(64, temp1, x, y); // Result bits 0..63
|
||||
smulh(64, temp2, x, y); // Result bits 64..127
|
||||
// Top is pure sign ext
|
||||
subs(64, zr, rscratch2, rscratch1, ShiftType.ASR, 63);
|
||||
subs(64, zr, temp2, temp1, ShiftType.ASR, 63);
|
||||
// Copy all 64 bits of the result into dst
|
||||
mov(64, dst, rscratch1);
|
||||
mov(rscratch1, 0x80000000);
|
||||
mov(64, dst, temp1);
|
||||
mov(temp1, 0x80000000);
|
||||
// Develop 0 (EQ), or 0x80000000 (NE)
|
||||
cmov(32, rscratch1, rscratch1, zr, ConditionFlag.NE);
|
||||
cmp(32, rscratch1, 1);
|
||||
cmov(32, temp1, temp1, zr, ConditionFlag.NE);
|
||||
cmp(32, temp1, 1);
|
||||
// 0x80000000 - 1 => VS
|
||||
break;
|
||||
}
|
||||
case 32: {
|
||||
Register rscratch1 = sc1.getRegister();
|
||||
smaddl(rscratch1, x, y, zr);
|
||||
Register temp1 = sc1.getRegister();
|
||||
smaddl(temp1, x, y, zr);
|
||||
// Copy the low 32 bits of the result into dst
|
||||
mov(32, dst, rscratch1);
|
||||
subs(64, zr, rscratch1, rscratch1, ExtendType.SXTW, 0);
|
||||
mov(32, dst, temp1);
|
||||
subs(64, zr, temp1, temp1, ExtendType.SXTW, 0);
|
||||
// NE => overflow
|
||||
mov(rscratch1, 0x80000000);
|
||||
mov(temp1, 0x80000000);
|
||||
// Develop 0 (EQ), or 0x80000000 (NE)
|
||||
cmov(32, rscratch1, rscratch1, zr, ConditionFlag.NE);
|
||||
cmp(32, rscratch1, 1);
|
||||
cmov(32, temp1, temp1, zr, ConditionFlag.NE);
|
||||
cmp(32, temp1, 1);
|
||||
// 0x80000000 - 1 => VS
|
||||
break;
|
||||
}
|
||||
|
@ -229,9 +229,12 @@ public class AArch64ArithmeticLIRGenerator extends ArithmeticLIRGenerator implem
|
||||
}
|
||||
|
||||
private Value emitMultiplyAddSub(AArch64ArithmeticOp op, Value a, Value b, Value c) {
|
||||
assert isNumericInteger(a.getPlatformKind());
|
||||
assert isNumericInteger(b.getPlatformKind());
|
||||
assert isNumericInteger(c.getPlatformKind());
|
||||
assert a.getPlatformKind() == b.getPlatformKind() && b.getPlatformKind() == c.getPlatformKind();
|
||||
if (op == AArch64ArithmeticOp.ADD || op == AArch64ArithmeticOp.SUB) {
|
||||
assert isNumericInteger(a.getPlatformKind());
|
||||
} else if (op == AArch64ArithmeticOp.FADD) {
|
||||
assert a.getPlatformKind() == AArch64Kind.SINGLE || a.getPlatformKind() == AArch64Kind.DOUBLE;
|
||||
}
|
||||
|
||||
Variable result = getLIRGen().newVariable(LIRKind.combine(a, b, c));
|
||||
AllocatableValue x = moveSp(asAllocatable(a));
|
||||
@ -446,6 +449,11 @@ public class AArch64ArithmeticLIRGenerator extends ArithmeticLIRGenerator implem
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value emitFusedMultiplyAdd(Value a, Value b, Value c) {
|
||||
return emitMultiplyAddSub(AArch64ArithmeticOp.FADD, a, b, c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value emitCountLeadingZeros(Value value) {
|
||||
Variable result = getLIRGen().newVariable(LIRKind.combine(value).changeType(AArch64Kind.DWORD));
|
||||
|
@ -48,6 +48,10 @@ import org.graalvm.compiler.lir.aarch64.AArch64AddressValue;
|
||||
import org.graalvm.compiler.lir.aarch64.AArch64ArithmeticOp;
|
||||
import org.graalvm.compiler.lir.aarch64.AArch64ArrayCompareToOp;
|
||||
import org.graalvm.compiler.lir.aarch64.AArch64ArrayEqualsOp;
|
||||
import org.graalvm.compiler.lir.aarch64.AArch64AtomicMove.AtomicReadAndAddLSEOp;
|
||||
import org.graalvm.compiler.lir.aarch64.AArch64AtomicMove.AtomicReadAndAddOp;
|
||||
import org.graalvm.compiler.lir.aarch64.AArch64AtomicMove.AtomicReadAndWriteOp;
|
||||
import org.graalvm.compiler.lir.aarch64.AArch64AtomicMove.CompareAndSwapOp;
|
||||
import org.graalvm.compiler.lir.aarch64.AArch64ByteSwapOp;
|
||||
import org.graalvm.compiler.lir.aarch64.AArch64Compare;
|
||||
import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow;
|
||||
@ -59,10 +63,6 @@ import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow.StrategySwitchOp;
|
||||
import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow.TableSwitchOp;
|
||||
import org.graalvm.compiler.lir.aarch64.AArch64LIRFlagsVersioned;
|
||||
import org.graalvm.compiler.lir.aarch64.AArch64Move;
|
||||
import org.graalvm.compiler.lir.aarch64.AArch64AtomicMove.AtomicReadAndAddOp;
|
||||
import org.graalvm.compiler.lir.aarch64.AArch64AtomicMove.AtomicReadAndAddLSEOp;
|
||||
import org.graalvm.compiler.lir.aarch64.AArch64AtomicMove.CompareAndSwapOp;
|
||||
import org.graalvm.compiler.lir.aarch64.AArch64AtomicMove.AtomicReadAndWriteOp;
|
||||
import org.graalvm.compiler.lir.aarch64.AArch64Move.MembarOp;
|
||||
import org.graalvm.compiler.lir.aarch64.AArch64PauseOp;
|
||||
import org.graalvm.compiler.lir.aarch64.AArch64SpeculativeBarrier;
|
||||
@ -586,8 +586,15 @@ public abstract class AArch64LIRGenerator extends LIRGenerator {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void emitZeroMemory(Value address, Value length) {
|
||||
// Value address is 8-byte aligned; Value length is multiple of 8.
|
||||
append(new AArch64ZeroMemoryOp(asAllocatable(address), asAllocatable(length), false, -1));
|
||||
public void emitZeroMemory(Value address, Value length, boolean isAligned) {
|
||||
emitZeroMemory(address, length, isAligned, false, -1);
|
||||
}
|
||||
|
||||
protected final void emitZeroMemory(Value address, Value length, boolean isAligned, boolean useDcZva, int zvaLength) {
|
||||
RegisterValue regAddress = AArch64.r0.asValue(address.getValueKind());
|
||||
RegisterValue regLength = AArch64.r1.asValue(length.getValueKind());
|
||||
emitMove(regAddress, address);
|
||||
emitMove(regLength, length);
|
||||
append(new AArch64ZeroMemoryOp(regAddress, regLength, isAligned, useDcZva, zvaLength));
|
||||
}
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ public interface AArch64LoweringProviderMixin extends LoweringProvider {
|
||||
}
|
||||
|
||||
@Override
|
||||
default int bulkZeroingStride() {
|
||||
return 8;
|
||||
default boolean supportsBulkZeroing() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -687,7 +687,7 @@ public abstract class AMD64LIRGenerator extends LIRGenerator {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void emitZeroMemory(Value address, Value length) {
|
||||
public void emitZeroMemory(Value address, Value length, boolean isAligned) {
|
||||
RegisterValue lengthReg = AMD64.rcx.asValue(length.getValueKind());
|
||||
emitMove(lengthReg, length);
|
||||
append(new AMD64ZeroMemoryOp(asAddressValue(address), lengthReg));
|
||||
|
@ -35,7 +35,7 @@ public interface AMD64LoweringProviderMixin extends LoweringProvider {
|
||||
}
|
||||
|
||||
@Override
|
||||
default int bulkZeroingStride() {
|
||||
return 1;
|
||||
default boolean supportsBulkZeroing() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ public interface SparcLoweringProviderMixin extends LoweringProvider {
|
||||
}
|
||||
|
||||
@Override
|
||||
default int bulkZeroingStride() {
|
||||
return 0;
|
||||
default boolean supportsBulkZeroing() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -432,6 +432,16 @@ public class CheckGraalInvariants extends GraalCompilerTest {
|
||||
try {
|
||||
Class<?> c = Class.forName(className, true, CheckGraalInvariants.class.getClassLoader());
|
||||
classes.add(c);
|
||||
} catch (UnsupportedClassVersionError e) {
|
||||
// graal-test.jar can contain classes compiled for different Java versions
|
||||
} catch (NoClassDefFoundError e) {
|
||||
if (!e.getMessage().contains("Could not initialize class")) {
|
||||
throw e;
|
||||
} else {
|
||||
// A second or later attempt to initialize a class
|
||||
// results in this confusing error where the
|
||||
// original cause of initialization failure is lost
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
tool.handleClassLoadingException(t);
|
||||
}
|
||||
|
@ -0,0 +1,176 @@
|
||||
/*
|
||||
* 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 java.lang.invoke.ConstantCallSite;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
|
||||
import org.graalvm.compiler.nodes.util.GraphUtil;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.Label;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
|
||||
import jdk.vm.ci.code.BailoutException;
|
||||
import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||
|
||||
/**
|
||||
* Unit tests derived from https://github.com/oracle/graal/pull/1690.
|
||||
*/
|
||||
public class GraphUtilOriginalValueTests extends CustomizedBytecodePatternTest {
|
||||
|
||||
static class LinkedNode {
|
||||
LinkedNode next;
|
||||
}
|
||||
|
||||
static class A extends LinkedNode {
|
||||
}
|
||||
|
||||
static class B extends LinkedNode {
|
||||
}
|
||||
|
||||
static class C extends LinkedNode {
|
||||
}
|
||||
|
||||
public static Class<?> getLastClass(A a) {
|
||||
LinkedNode current = a;
|
||||
Class<?> currentKlass = null;
|
||||
while (current != null) {
|
||||
// This must not be folded to A.class
|
||||
currentKlass = current.getClass();
|
||||
|
||||
current = current.next;
|
||||
}
|
||||
return currentKlass;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetClass() {
|
||||
A a = new A();
|
||||
a.next = new B();
|
||||
|
||||
test("getLastClass", a);
|
||||
}
|
||||
|
||||
static final ConstantCallSite cs1 = init(A.class);
|
||||
static final ConstantCallSite cs2 = init(B.class);
|
||||
static final ConstantCallSite cs3 = init(C.class);
|
||||
|
||||
static ConstantCallSite init(Class<?> c) {
|
||||
try {
|
||||
return new ConstantCallSite(MethodHandles.lookup().unreflectConstructor(c.getDeclaredConstructor()));
|
||||
} catch (Exception e) {
|
||||
throw new InternalError(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean findTarget(MethodHandle key) {
|
||||
ConstantCallSite cs = cs1;
|
||||
while (cs != null) {
|
||||
if (cs.getTarget() == key) {
|
||||
return true;
|
||||
}
|
||||
if (cs == cs1) {
|
||||
cs = cs2;
|
||||
} else if (cs == cs2) {
|
||||
cs = cs3;
|
||||
} else {
|
||||
cs = null;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTarget() {
|
||||
cs1.getTarget();
|
||||
cs2.getTarget();
|
||||
test("findTarget", cs3.getTarget());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte[] generateClass(String internalClassName) {
|
||||
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
|
||||
cw.visit(52, ACC_SUPER | ACC_PUBLIC, internalClassName, null, "java/lang/Object", null);
|
||||
|
||||
String getDescriptor = "(Ljava/lang/Object;)V";
|
||||
MethodVisitor m = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "unbalancedMonitors", getDescriptor, null, null);
|
||||
Label loopHead = new Label();
|
||||
Label end = new Label();
|
||||
m.visitCode();
|
||||
|
||||
// @formatter:off
|
||||
/*
|
||||
* void unbalancedMonitors(Object o) {
|
||||
* monitorenter(o);
|
||||
* while (o.toString() != o) {
|
||||
* monitorexit(o);
|
||||
* o = o.toString();
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
// @formatter:on
|
||||
|
||||
m.visitVarInsn(ALOAD, 0);
|
||||
m.visitInsn(MONITORENTER);
|
||||
m.visitLabel(loopHead);
|
||||
m.visitVarInsn(ALOAD, 0);
|
||||
m.visitInsn(MONITOREXIT);
|
||||
m.visitVarInsn(ALOAD, 0);
|
||||
m.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "toString", "()Ljava/lang/String;", false);
|
||||
m.visitVarInsn(ALOAD, 0);
|
||||
m.visitJumpInsn(IF_ACMPEQ, end);
|
||||
m.visitVarInsn(ALOAD, 0);
|
||||
m.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "toString", "()Ljava/lang/String;", false);
|
||||
m.visitVarInsn(ASTORE, 0);
|
||||
m.visitJumpInsn(GOTO, loopHead);
|
||||
m.visitLabel(end);
|
||||
m.visitInsn(RETURN);
|
||||
m.visitMaxs(2, 2);
|
||||
m.visitEnd();
|
||||
|
||||
cw.visitEnd();
|
||||
return cw.toByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the use of {@link GraphUtil#originalValue} in parsing MONITOREXIT correctly
|
||||
* detects unbalanced monitors.
|
||||
*/
|
||||
@Test
|
||||
public void testUnbalancedMonitors() throws ClassNotFoundException {
|
||||
Class<?> testClass = getClass("UnbalancedMonitors");
|
||||
ResolvedJavaMethod t1 = getResolvedJavaMethod(testClass, "unbalancedMonitors");
|
||||
try {
|
||||
parseForCompile(t1);
|
||||
Assert.fail("expected a " + BailoutException.class.getName());
|
||||
} catch (BailoutException e) {
|
||||
String msg = e.getMessage();
|
||||
Assert.assertTrue(msg, msg.contains("unbalanced monitors"));
|
||||
}
|
||||
}
|
||||
}
|
@ -87,8 +87,8 @@ public class VerifySystemPropertyUsage extends VerifyPhase<CoreProviders> {
|
||||
} else if (holderQualified.equals("org.graalvm.compiler.hotspot.JVMCIVersionCheck") && caller.getName().equals("main")) {
|
||||
// The main method in JVMCIVersionCheck is only called from the shell
|
||||
return;
|
||||
} else if (packageName.startsWith("com.oracle.truffle") || packageName.startsWith("org.graalvm.polyglot")) {
|
||||
// Truffle and Polyglot do not depend on JVMCI so cannot use
|
||||
} else if (packageName.startsWith("com.oracle.truffle") || packageName.startsWith("org.graalvm.polyglot") || packageName.startsWith("org.graalvm.home")) {
|
||||
// Truffle and SDK do not depend on JVMCI so they cannot use
|
||||
// Services.getSavedProperties()
|
||||
return;
|
||||
} else if (packageName.startsWith("com.oracle.svm")) {
|
||||
|
@ -40,7 +40,10 @@ import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import org.graalvm.graphio.GraphOutput;
|
||||
import org.graalvm.graphio.GraphStructure;
|
||||
import org.graalvm.graphio.GraphTypes;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import org.junit.Test;
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
public final class GraphOutputTest {
|
||||
|
||||
@ -116,6 +119,18 @@ public final class GraphOutputTest {
|
||||
assertArrayEquals(expected.toByteArray(), embedded.toByteArray());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings({"static-method", "unchecked"})
|
||||
public void testClassOfEnumValueWithImplementation() throws ClassNotFoundException, ReflectiveOperationException {
|
||||
Class<? extends GraphTypes> defaultTypesClass = (Class<? extends GraphTypes>) Class.forName("org.graalvm.graphio.DefaultGraphTypes");
|
||||
Field f = defaultTypesClass.getDeclaredField("DEFAULT");
|
||||
f.setAccessible(true);
|
||||
GraphTypes types = (GraphTypes) f.get(null);
|
||||
|
||||
Object clazz = types.enumClass(CustomEnum.ONE);
|
||||
assertSame(CustomEnum.class, clazz);
|
||||
}
|
||||
|
||||
private static ByteBuffer generateData(int size) {
|
||||
ByteBuffer buffer = ByteBuffer.allocate(size);
|
||||
for (int i = 0; i < size; i++) {
|
||||
@ -281,4 +296,20 @@ public final class GraphOutputTest {
|
||||
|
||||
private static final class MockGraph {
|
||||
}
|
||||
|
||||
private enum CustomEnum {
|
||||
ONE() {
|
||||
@Override
|
||||
public String toString() {
|
||||
return "one";
|
||||
}
|
||||
},
|
||||
|
||||
TWO() {
|
||||
@Override
|
||||
public String toString() {
|
||||
return "two";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -741,6 +741,7 @@ public final class NodeClass<T> extends FieldIntrospection<T> {
|
||||
} else {
|
||||
Object objectA = data.getObject(a, i);
|
||||
Object objectB = data.getObject(b, i);
|
||||
assert !isLambda(objectA) || !isLambda(objectB) : "lambdas are not permitted in fields of " + this.toString();
|
||||
if (objectA != objectB) {
|
||||
if (objectA != null && objectB != null) {
|
||||
if (!deepEquals0(objectA, objectB)) {
|
||||
@ -755,6 +756,11 @@ public final class NodeClass<T> extends FieldIntrospection<T> {
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean isLambda(Object obj) {
|
||||
// This needs to be consistent with InnerClassLambdaMetafactory constructor.
|
||||
return obj != null && obj.getClass().getSimpleName().contains("$$Lambda$");
|
||||
}
|
||||
|
||||
public boolean isValid(Position pos, NodeClass<?> from, Edges fromEdges) {
|
||||
if (this == from) {
|
||||
return true;
|
||||
|
@ -122,10 +122,6 @@ public abstract class NodeList<T extends Node> extends AbstractList<T> implement
|
||||
size = newSize;
|
||||
}
|
||||
|
||||
public boolean isList() {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected abstract void update(T oldNode, T newNode);
|
||||
|
||||
public abstract Edges.Type getEdgesType();
|
||||
|
@ -95,6 +95,9 @@ public class NodeMap<T> extends NodeIdAccessor implements EconomicMap<Node, T> {
|
||||
|
||||
public void set(Node node, T value) {
|
||||
assert check(node);
|
||||
if (!node.isAlive()) {
|
||||
throw new VerificationError("this node is not alive: " + node);
|
||||
}
|
||||
values[getNodeId(node)] = value;
|
||||
}
|
||||
|
||||
|
@ -192,7 +192,7 @@ public class AArch64HotSpotBackendFactory extends HotSpotBackendFactory {
|
||||
replacements,
|
||||
options);
|
||||
AArch64GraphBuilderPlugins.register(plugins, replacements.getDefaultReplacementBytecodeProvider(), false,
|
||||
/* registerMathPlugins */true);
|
||||
/* registerMathPlugins */true, /* emitJDK9StringSubstitutions */true, config.useFMAIntrinsics);
|
||||
return plugins;
|
||||
}
|
||||
|
||||
|
@ -84,7 +84,6 @@ import org.graalvm.compiler.lir.aarch64.AArch64Move.StoreOp;
|
||||
import org.graalvm.compiler.lir.aarch64.AArch64PrefetchOp;
|
||||
import org.graalvm.compiler.lir.aarch64.AArch64RestoreRegistersOp;
|
||||
import org.graalvm.compiler.lir.aarch64.AArch64SaveRegistersOp;
|
||||
import org.graalvm.compiler.lir.aarch64.AArch64ZeroMemoryOp;
|
||||
import org.graalvm.compiler.lir.gen.LIRGenerationResult;
|
||||
import org.graalvm.compiler.options.OptionValues;
|
||||
|
||||
@ -544,7 +543,7 @@ public class AArch64HotSpotLIRGenerator extends AArch64LIRGenerator implements H
|
||||
}
|
||||
|
||||
@Override
|
||||
public void emitZeroMemory(Value address, Value length) {
|
||||
public void emitZeroMemory(Value address, Value length, boolean isAligned) {
|
||||
int dczidValue = config.psrInfoDczidValue;
|
||||
EnumSet<AArch64.Flag> flags = ((AArch64) target().arch).getFlags();
|
||||
|
||||
@ -563,7 +562,6 @@ public class AArch64HotSpotLIRGenerator extends AArch64LIRGenerator implements H
|
||||
useDcZva = false;
|
||||
}
|
||||
|
||||
// Value address is 8-byte aligned; Value length is multiple of 8.
|
||||
append(new AArch64ZeroMemoryOp(asAllocatable(address), asAllocatable(length), useDcZva, zvaLength));
|
||||
emitZeroMemory(address, length, isAligned, useDcZva, zvaLength);
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
@ -45,7 +45,10 @@ import static jdk.vm.ci.aarch64.AArch64.r24;
|
||||
import static jdk.vm.ci.aarch64.AArch64.r25;
|
||||
import static jdk.vm.ci.aarch64.AArch64.r26;
|
||||
import static jdk.vm.ci.aarch64.AArch64.r28;
|
||||
import static jdk.vm.ci.aarch64.AArch64.r29;
|
||||
import static jdk.vm.ci.aarch64.AArch64.r3;
|
||||
import static jdk.vm.ci.aarch64.AArch64.r30;
|
||||
import static jdk.vm.ci.aarch64.AArch64.r31;
|
||||
import static jdk.vm.ci.aarch64.AArch64.r4;
|
||||
import static jdk.vm.ci.aarch64.AArch64.r5;
|
||||
import static jdk.vm.ci.aarch64.AArch64.r6;
|
||||
@ -96,12 +99,22 @@ import jdk.vm.ci.code.RegisterConfig;
|
||||
|
||||
public class AArch64HotSpotRegisterAllocationConfig extends RegisterAllocationConfig {
|
||||
|
||||
/**
|
||||
* Excluding r27 is a temporary solution until we exclude r27 unconditionally at
|
||||
* {@link jdk.vm.ci.hotspot.aarch64.AArch64HotSpotRegisterConfig}.
|
||||
*
|
||||
* The underlying reason is that HotSpot does not intend to support r27 as an allocatable
|
||||
* register. This register is excluded from callee-saved register at
|
||||
* cpu/aarch64/sharedRuntime_aarch64.cpp:RegisterSaver::save_live_registers, and may lead to
|
||||
* dereferencing unknown value from the stack at
|
||||
* share/runtime/stackValue.cpp:StackValue::create_stack_value during deoptimization.
|
||||
*/
|
||||
// @formatter:off
|
||||
static final Register[] registerAllocationOrder = {
|
||||
r0, r1, r2, r3, r4, r5, r6, r7,
|
||||
r8, r9, r10, r11, r12, r13, r14, r15,
|
||||
r16, r17, r18, r19, r20, r21, r22, r23,
|
||||
r24, r25, r26, /* r27, */ r28, /* r29, r30, r31 */
|
||||
r24, r25, r26, /* r27, */ r28, r29, r30, r31,
|
||||
|
||||
v0, v1, v2, v3, v4, v5, v6, v7,
|
||||
v8, v9, v10, v11, v12, v13, v14, v15,
|
||||
|
@ -76,23 +76,22 @@ public class MitigateExceedingMaxOopMapStackOffsetTest extends LIRTest {
|
||||
// Place reference slots at top and bottom of virtual frame
|
||||
// with primitive slots in the middle. This tests that slot
|
||||
// partitioning works.
|
||||
AllocatableValue srcObject = gen.emitLoadConstant(objectLirKind, objectConstant);
|
||||
for (int i = 0; i < numReferenceSlots / 2; i++) {
|
||||
AllocatableValue src = gen.emitLoadConstant(objectLirKind, objectConstant);
|
||||
VirtualStackSlot slot = frameMapBuilder.allocateSpillSlot(objectLirKind);
|
||||
slotList.add(slot);
|
||||
gen.emitMove(slot, src);
|
||||
gen.emitMove(slot, srcObject);
|
||||
}
|
||||
AllocatableValue srcPrimitive = gen.emitLoadConstant(objectLirKind, primitiveConstant);
|
||||
for (int i = 0; i < numPrimitiveSlots; i++) {
|
||||
AllocatableValue src = gen.emitLoadConstant(objectLirKind, primitiveConstant);
|
||||
VirtualStackSlot slot = frameMapBuilder.allocateSpillSlot(primitiveLirKind);
|
||||
slotList.add(slot);
|
||||
gen.emitMove(slot, src);
|
||||
gen.emitMove(slot, srcPrimitive);
|
||||
}
|
||||
for (int i = numReferenceSlots / 2; i < numReferenceSlots; i++) {
|
||||
AllocatableValue src = gen.emitLoadConstant(objectLirKind, objectConstant);
|
||||
VirtualStackSlot slot = frameMapBuilder.allocateSpillSlot(objectLirKind);
|
||||
slotList.add(slot);
|
||||
gen.emitMove(slot, src);
|
||||
gen.emitMove(slot, srcObject);
|
||||
}
|
||||
slots = slotList.toArray(new AllocatableValue[slotList.size()]);
|
||||
}
|
||||
|
@ -64,6 +64,7 @@ import jdk.vm.ci.meta.MetaAccessProvider;
|
||||
import jdk.vm.ci.meta.MetaUtil;
|
||||
import jdk.vm.ci.meta.MethodHandleAccessProvider.IntrinsicMethod;
|
||||
import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||
import jdk.vm.ci.sparc.SPARC;
|
||||
|
||||
/**
|
||||
* Checks the intrinsics implemented by Graal against the set of intrinsics declared by HotSpot. The
|
||||
@ -375,7 +376,7 @@ public class CheckGraalIntrinsics extends GraalTest {
|
||||
add(ignore,
|
||||
"java/lang/Math.fma(DDD)D",
|
||||
"java/lang/Math.fma(FFF)F");
|
||||
} else if (!(arch instanceof AMD64)) {
|
||||
} else if (arch instanceof SPARC) {
|
||||
add(toBeInvestigated,
|
||||
"java/lang/Math.fma(DDD)D",
|
||||
"java/lang/Math.fma(FFF)F");
|
||||
|
@ -25,8 +25,6 @@
|
||||
|
||||
package org.graalvm.compiler.hotspot.test;
|
||||
|
||||
import static org.graalvm.compiler.serviceprovider.JavaVersionUtil.JAVA_SPEC;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.graalvm.compiler.core.test.GraalCompilerTest;
|
||||
@ -75,9 +73,27 @@ public class ConstantPoolSubstitutionsTests extends GraalCompilerTest {
|
||||
return graph;
|
||||
}
|
||||
|
||||
private static String getMiscPackage() {
|
||||
if (JavaVersionUtil.JAVA_SPEC <= 8) {
|
||||
return "sun.misc";
|
||||
}
|
||||
try {
|
||||
String miscPackage = "jdk.internal.access";
|
||||
Class.forName(miscPackage + ".SharedSecrets");
|
||||
return miscPackage;
|
||||
} catch (ClassNotFoundException e) {
|
||||
try {
|
||||
String miscPackage = "jdk.internal.misc";
|
||||
Class.forName(miscPackage + ".SharedSecrets");
|
||||
return miscPackage;
|
||||
} catch (ClassNotFoundException ex) {
|
||||
}
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static Object getConstantPoolForObject() {
|
||||
String miscPackage = JavaVersionUtil.JAVA_SPEC <= 8 ? "sun.misc"
|
||||
: (JavaVersionUtil.JAVA_SPEC <= 11 ? "jdk.internal.misc" : "jdk.internal.access");
|
||||
String miscPackage = getMiscPackage();
|
||||
try {
|
||||
Class<?> sharedSecretsClass = Class.forName(miscPackage + ".SharedSecrets");
|
||||
Class<?> javaLangAccessClass = Class.forName(miscPackage + ".JavaLangAccess");
|
||||
@ -112,8 +128,7 @@ public class ConstantPoolSubstitutionsTests extends GraalCompilerTest {
|
||||
* This test uses some non-public API.
|
||||
*/
|
||||
private static void addExports(Class<?> c) {
|
||||
String packageName = JAVA_SPEC <= 11 ? "jdk.internal.misc" : "jdk.internal.access";
|
||||
ModuleSupport.exportPackageTo(String.class, packageName, c);
|
||||
ModuleSupport.exportPackageTo(String.class, getMiscPackage(), c);
|
||||
ModuleSupport.exportPackageTo(String.class, "jdk.internal.reflect", c);
|
||||
}
|
||||
|
||||
|
@ -321,6 +321,7 @@ public class GraalHotSpotVMConfig extends GraalHotSpotVMConfigBase {
|
||||
public final int jvmciCountersThreadOffset = getFieldOffset("JavaThread::_jvmci_counters", Integer.class, "jlong*");
|
||||
public final int doingUnsafeAccessOffset = getFieldOffset("JavaThread::_doing_unsafe_access", Integer.class, "bool", Integer.MAX_VALUE);
|
||||
public final int javaThreadReservedStackActivationOffset = versioned.javaThreadReservedStackActivationOffset;
|
||||
public final int jniEnvironmentOffset = getFieldOffset("JavaThread::_jni_environment", Integer.class, "JNIEnv", Integer.MIN_VALUE);
|
||||
|
||||
public boolean requiresReservedStackCheck(List<ResolvedJavaMethod> methods) {
|
||||
if (enableStackReservedZoneAddress != 0 && methods != null) {
|
||||
|
@ -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.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -35,7 +35,7 @@ public interface HotSpotGraalManagementRegistration {
|
||||
* Completes the initialization of this registration by recording the
|
||||
* {@link HotSpotGraalRuntime} the MBean will provide an JMX interface to.
|
||||
*/
|
||||
void initialize(HotSpotGraalRuntime runtime);
|
||||
void initialize(HotSpotGraalRuntime runtime, GraalHotSpotVMConfig config);
|
||||
|
||||
/**
|
||||
* Polls this registration to see if the MBean is registered in a MBean server.
|
||||
|
@ -35,6 +35,7 @@ import java.util.EnumMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import jdk.internal.vm.compiler.collections.EconomicMap;
|
||||
import jdk.internal.vm.compiler.collections.EconomicSet;
|
||||
@ -97,6 +98,10 @@ import jdk.vm.ci.services.Services;
|
||||
public final class HotSpotGraalRuntime implements HotSpotGraalRuntimeProvider {
|
||||
|
||||
private static final boolean IS_AOT = Boolean.parseBoolean(Services.getSavedProperties().get("com.oracle.graalvm.isaot"));
|
||||
/**
|
||||
* A factory for {@link HotSpotGraalManagementRegistration} injected by {@code LibGraalFeature}.
|
||||
*/
|
||||
private static final Supplier<HotSpotGraalManagementRegistration> AOT_INJECTED_MANAGEMENT = null;
|
||||
|
||||
private static boolean checkArrayIndexScaleInvariants(MetaAccessProvider metaAccess) {
|
||||
assert metaAccess.getArrayIndexScale(JavaKind.Byte) == 1;
|
||||
@ -165,12 +170,12 @@ public final class HotSpotGraalRuntime implements HotSpotGraalRuntimeProvider {
|
||||
compilerConfigurationName = compilerConfigurationFactory.getName();
|
||||
|
||||
if (IS_AOT) {
|
||||
management = null;
|
||||
management = AOT_INJECTED_MANAGEMENT == null ? null : AOT_INJECTED_MANAGEMENT.get();
|
||||
} else {
|
||||
management = GraalServices.loadSingle(HotSpotGraalManagementRegistration.class, false);
|
||||
if (management != null) {
|
||||
management.initialize(this);
|
||||
}
|
||||
}
|
||||
if (management != null) {
|
||||
management.initialize(this, config);
|
||||
}
|
||||
|
||||
BackendMap backendMap = compilerConfigurationFactory.createBackendMap();
|
||||
@ -292,13 +297,15 @@ public final class HotSpotGraalRuntime implements HotSpotGraalRuntimeProvider {
|
||||
HotSpotResolvedObjectType type = ((HotSpotResolvedJavaMethod) compilable).getDeclaringClass();
|
||||
if (type instanceof HotSpotResolvedJavaType) {
|
||||
Class<?> clazz = runtime().getMirror(type);
|
||||
try {
|
||||
ClassLoader cl = clazz.getClassLoader();
|
||||
if (cl != null) {
|
||||
loaders.add(cl);
|
||||
if (clazz != null) {
|
||||
try {
|
||||
ClassLoader cl = clazz.getClassLoader();
|
||||
if (cl != null) {
|
||||
loaders.add(cl);
|
||||
}
|
||||
} catch (SecurityException e) {
|
||||
// This loader can obviously not be used for resolving class names
|
||||
}
|
||||
} catch (SecurityException e) {
|
||||
// This loader can obviously not be used for resolving class names
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ import java.util.regex.Pattern;
|
||||
*/
|
||||
public final class JVMCIVersionCheck {
|
||||
|
||||
private static final Version JVMCI8_MIN_VERSION = new Version3(19, 2, 1);
|
||||
private static final Version JVMCI8_MIN_VERSION = new Version3(19, 3, 2);
|
||||
|
||||
public interface Version {
|
||||
boolean isLessThan(Version other);
|
||||
@ -230,6 +230,17 @@ public final class JVMCIVersionCheck {
|
||||
failVersionCheck(props, exitOnFailure, "Could not parse the JDK 11 early access build number from java.vm.version property: %s.%n", vmVersion);
|
||||
return;
|
||||
}
|
||||
} else if (vmVersion.contains("-jvmci-")) {
|
||||
// A "labsjdk"
|
||||
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);
|
||||
} else {
|
||||
// Graal is compatible with all JDK versions as of 11 GA.
|
||||
}
|
||||
|
@ -254,7 +254,7 @@ public class HotSpotGraphBuilderPlugins {
|
||||
@Override
|
||||
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
|
||||
ValueNode callSite = receiver.get();
|
||||
ValueNode folded = CallSiteTargetNode.tryFold(GraphUtil.originalValue(callSite), b.getMetaAccess(), b.getAssumptions());
|
||||
ValueNode folded = CallSiteTargetNode.tryFold(GraphUtil.originalValue(callSite, true), b.getMetaAccess(), b.getAssumptions());
|
||||
if (folded != null) {
|
||||
b.addPush(JavaKind.Object, folded);
|
||||
} else {
|
||||
|
@ -359,12 +359,12 @@ public class NewObjectSnippets implements Snippets {
|
||||
@ConstantParameter Register threadRegister,
|
||||
@ConstantParameter boolean maybeUnroll,
|
||||
@ConstantParameter String typeContext,
|
||||
@ConstantParameter int bulkZeroingStride,
|
||||
@ConstantParameter boolean supportsBulkZeroing,
|
||||
@ConstantParameter Counters counters) {
|
||||
// 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,
|
||||
emitMemoryBarrier, threadRegister, maybeUnroll, typeContext, bulkZeroingStride, counters);
|
||||
emitMemoryBarrier, threadRegister, maybeUnroll, typeContext, supportsBulkZeroing, counters);
|
||||
}
|
||||
|
||||
@Snippet
|
||||
@ -378,12 +378,12 @@ public class NewObjectSnippets implements Snippets {
|
||||
@ConstantParameter Register threadRegister,
|
||||
@ConstantParameter boolean maybeUnroll,
|
||||
@ConstantParameter String typeContext,
|
||||
@ConstantParameter int bulkZeroingStride,
|
||||
@ConstantParameter boolean supportsBulkZeroing,
|
||||
@ConstantParameter Counters counters) {
|
||||
// Array type would be resolved by dominating resolution.
|
||||
KlassPointer picHub = LoadConstantIndirectlyFixedNode.loadKlass(hub);
|
||||
return allocateArrayImpl(picHub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents,
|
||||
emitMemoryBarrier, threadRegister, maybeUnroll, typeContext, bulkZeroingStride, counters);
|
||||
emitMemoryBarrier, threadRegister, maybeUnroll, typeContext, supportsBulkZeroing, counters);
|
||||
}
|
||||
|
||||
@Snippet
|
||||
@ -397,7 +397,7 @@ public class NewObjectSnippets implements Snippets {
|
||||
@ConstantParameter Register threadRegister,
|
||||
@ConstantParameter boolean maybeUnroll,
|
||||
@ConstantParameter String typeContext,
|
||||
@ConstantParameter int bulkZeroingStride,
|
||||
@ConstantParameter boolean supportsBulkZeroing,
|
||||
@ConstantParameter Counters counters) {
|
||||
Object result = allocateArrayImpl(hub,
|
||||
length,
|
||||
@ -408,7 +408,7 @@ public class NewObjectSnippets implements Snippets {
|
||||
emitMemoryBarrier, threadRegister,
|
||||
maybeUnroll,
|
||||
typeContext,
|
||||
bulkZeroingStride,
|
||||
supportsBulkZeroing,
|
||||
counters);
|
||||
return piArrayCastToSnippetReplaceeStamp(verifyOop(result), length);
|
||||
}
|
||||
@ -432,7 +432,7 @@ public class NewObjectSnippets implements Snippets {
|
||||
Register threadRegister,
|
||||
boolean maybeUnroll,
|
||||
String typeContext,
|
||||
int bulkZeroingStride,
|
||||
boolean supportsBulkZeroing,
|
||||
Counters counters) {
|
||||
Object result;
|
||||
long allocationSize = arrayAllocationSize(length, headerSize, log2ElementSize);
|
||||
@ -448,7 +448,7 @@ public class NewObjectSnippets implements Snippets {
|
||||
if (theCounters != null && theCounters.arrayLoopInit != null) {
|
||||
theCounters.arrayLoopInit.inc();
|
||||
}
|
||||
result = formatArray(hub, allocationSize, length, headerSize, top, prototypeMarkWord, fillContents, emitMemoryBarrier, maybeUnroll, bulkZeroingStride, counters);
|
||||
result = formatArray(hub, allocationSize, length, headerSize, top, prototypeMarkWord, fillContents, emitMemoryBarrier, maybeUnroll, supportsBulkZeroing, counters);
|
||||
} else {
|
||||
result = newArrayStub(hub, length);
|
||||
}
|
||||
@ -513,11 +513,11 @@ public class NewObjectSnippets implements Snippets {
|
||||
@ConstantParameter Register threadRegister,
|
||||
@ConstantParameter JavaKind knownElementKind,
|
||||
@ConstantParameter int knownLayoutHelper,
|
||||
@ConstantParameter int bulkZeroingStride,
|
||||
@ConstantParameter boolean supportsBulkZeroing,
|
||||
Word prototypeMarkWord,
|
||||
@ConstantParameter Counters counters) {
|
||||
Object result = allocateArrayDynamicImpl(elementType, voidClass, length, fillContents, emitMemoryBarrier, threadRegister, knownElementKind,
|
||||
knownLayoutHelper, bulkZeroingStride, prototypeMarkWord, counters);
|
||||
knownLayoutHelper, supportsBulkZeroing, prototypeMarkWord, counters);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -529,7 +529,7 @@ public class NewObjectSnippets implements Snippets {
|
||||
Register threadRegister,
|
||||
JavaKind knownElementKind,
|
||||
int knownLayoutHelper,
|
||||
int bulkZeroingStride,
|
||||
boolean supportsBulkZeroing,
|
||||
Word prototypeMarkWord,
|
||||
Counters counters) {
|
||||
/*
|
||||
@ -574,7 +574,7 @@ public class NewObjectSnippets implements Snippets {
|
||||
int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift(INJECTED_VMCONFIG)) & layoutHelperLog2ElementSizeMask(INJECTED_VMCONFIG);
|
||||
|
||||
Object result = allocateArrayImpl(nonNullKlass, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents,
|
||||
emitMemoryBarrier, threadRegister, false, "dynamic type", bulkZeroingStride, counters);
|
||||
emitMemoryBarrier, threadRegister, false, "dynamic type", supportsBulkZeroing, counters);
|
||||
return piArrayCastToSnippetReplaceeStamp(verifyOop(result), length);
|
||||
}
|
||||
|
||||
@ -627,16 +627,16 @@ public class NewObjectSnippets implements Snippets {
|
||||
* @param endOffset offset to stop zeroing (exclusive). May not be word aligned.
|
||||
* @param isEndOffsetConstant is {@code endOffset} known to be constant in the snippet
|
||||
* @param manualUnroll maximally unroll zeroing
|
||||
* @param bulkZeroingStride stride of bulk zeroing supported by the backend
|
||||
* @param supportsBulkZeroing whether bulk zeroing is supported by the backend
|
||||
*/
|
||||
private static void zeroMemory(Word memory, int startOffset, long endOffset, boolean isEndOffsetConstant, boolean manualUnroll,
|
||||
int bulkZeroingStride, Counters counters) {
|
||||
fillMemory(0, memory, startOffset, endOffset, isEndOffsetConstant, manualUnroll, bulkZeroingStride, counters);
|
||||
boolean supportsBulkZeroing, Counters counters) {
|
||||
fillMemory(0, memory, startOffset, endOffset, isEndOffsetConstant, manualUnroll, supportsBulkZeroing, counters);
|
||||
}
|
||||
|
||||
private static void fillMemory(long value, Word memory, int startOffset, long offsetLimit, boolean constantOffsetLimit, boolean manualUnroll,
|
||||
int bulkZeroingStride, Counters counters) {
|
||||
ReplacementsUtil.runtimeAssert((offsetLimit & 0x7) == 0, "unaligned object size");
|
||||
private static void fillMemory(long value, Word memory, int startOffset, long endOffset, boolean constantOffsetLimit, boolean manualUnroll,
|
||||
boolean supportsBulkZeroing, Counters counters) {
|
||||
ReplacementsUtil.runtimeAssert((endOffset & 0x7) == 0, "unaligned object size");
|
||||
int offset = startOffset;
|
||||
if ((offset & 0x7) != 0) {
|
||||
memory.writeInt(offset, (int) value, LocationIdentity.init());
|
||||
@ -644,7 +644,7 @@ public class NewObjectSnippets implements Snippets {
|
||||
}
|
||||
ReplacementsUtil.runtimeAssert((offset & 0x7) == 0, "unaligned offset");
|
||||
Counters theCounters = counters;
|
||||
if (manualUnroll && ((offsetLimit - offset) / 8) <= MAX_UNROLLED_OBJECT_ZEROING_STORES) {
|
||||
if (manualUnroll && ((endOffset - offset) / 8) <= MAX_UNROLLED_OBJECT_ZEROING_STORES) {
|
||||
ReplacementsUtil.staticAssert(!constantOffsetLimit, "size shouldn't be constant at instantiation time");
|
||||
// This case handles arrays of constant length. Instead of having a snippet variant for
|
||||
// each length, generate a chain of stores of maximum length. Once it's inlined the
|
||||
@ -655,7 +655,7 @@ public class NewObjectSnippets implements Snippets {
|
||||
|
||||
explodeLoop();
|
||||
for (int i = 0; i < MAX_UNROLLED_OBJECT_ZEROING_STORES; i++, offset += 8) {
|
||||
if (offset == offsetLimit) {
|
||||
if (offset == endOffset) {
|
||||
break;
|
||||
}
|
||||
memory.initializeLong(offset, value, LocationIdentity.init());
|
||||
@ -663,13 +663,13 @@ public class NewObjectSnippets implements Snippets {
|
||||
} else {
|
||||
// Use Word instead of int to avoid extension to long in generated code
|
||||
Word off = WordFactory.signed(offset);
|
||||
if (bulkZeroingStride > 0 && value == 0 && probability(SLOW_PATH_PROBABILITY, (offsetLimit - offset) >= getMinimalBulkZeroingSize(INJECTED_OPTIONVALUES))) {
|
||||
if (supportsBulkZeroing && value == 0 && probability(SLOW_PATH_PROBABILITY, (endOffset - offset) >= getMinimalBulkZeroingSize(INJECTED_OPTIONVALUES))) {
|
||||
if (theCounters != null && theCounters.instanceBulkInit != null) {
|
||||
theCounters.instanceBulkInit.inc();
|
||||
}
|
||||
ZeroMemoryNode.zero(memory.add(off), offsetLimit - offset, LocationIdentity.init());
|
||||
ZeroMemoryNode.zero(memory.add(off), endOffset - offset, true, LocationIdentity.init());
|
||||
} else {
|
||||
if (constantOffsetLimit && ((offsetLimit - offset) / 8) <= MAX_UNROLLED_OBJECT_ZEROING_STORES) {
|
||||
if (constantOffsetLimit && ((endOffset - offset) / 8) <= MAX_UNROLLED_OBJECT_ZEROING_STORES) {
|
||||
if (theCounters != null && theCounters.instanceSeqInit != null) {
|
||||
theCounters.instanceSeqInit.inc();
|
||||
}
|
||||
@ -679,7 +679,7 @@ public class NewObjectSnippets implements Snippets {
|
||||
theCounters.instanceLoopInit.inc();
|
||||
}
|
||||
}
|
||||
for (; off.rawValue() < offsetLimit; off = off.add(8)) {
|
||||
for (; off.rawValue() < endOffset; off = off.add(8)) {
|
||||
memory.initializeLong(off, value, LocationIdentity.init());
|
||||
}
|
||||
}
|
||||
@ -703,7 +703,7 @@ public class NewObjectSnippets implements Snippets {
|
||||
* @param manualUnroll maximally unroll zeroing
|
||||
*/
|
||||
private static void fillWithGarbage(Word memory, int startOffset, long endOffset, boolean isEndOffsetConstant, boolean manualUnroll, Counters counters) {
|
||||
fillMemory(0xfefefefefefefefeL, memory, startOffset, endOffset, isEndOffsetConstant, manualUnroll, 0, counters);
|
||||
fillMemory(0xfefefefefefefefeL, memory, startOffset, endOffset, isEndOffsetConstant, manualUnroll, false, counters);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -720,7 +720,7 @@ public class NewObjectSnippets implements Snippets {
|
||||
Word prototypeMarkWord = useBiasedLocking(INJECTED_VMCONFIG) ? hub.readWord(prototypeMarkWordOffset(INJECTED_VMCONFIG), PROTOTYPE_MARK_WORD_LOCATION) : compileTimePrototypeMarkWord;
|
||||
initializeObjectHeader(memory, prototypeMarkWord, hub);
|
||||
if (fillContents) {
|
||||
zeroMemory(memory, instanceHeaderSize(INJECTED_VMCONFIG), size, constantSize, false, 0, counters);
|
||||
zeroMemory(memory, instanceHeaderSize(INJECTED_VMCONFIG), size, constantSize, false, false, counters);
|
||||
} else if (REPLACEMENTS_ASSERTIONS_ENABLED) {
|
||||
fillWithGarbage(memory, instanceHeaderSize(INJECTED_VMCONFIG), size, constantSize, false, counters);
|
||||
}
|
||||
@ -767,7 +767,7 @@ public class NewObjectSnippets implements Snippets {
|
||||
boolean fillContents,
|
||||
boolean emitMemoryBarrier,
|
||||
boolean maybeUnroll,
|
||||
int bulkZeroingStride,
|
||||
boolean supportsBulkZeroing,
|
||||
Counters counters) {
|
||||
memory.writeInt(arrayLengthOffset(INJECTED_VMCONFIG), length, LocationIdentity.init());
|
||||
/*
|
||||
@ -776,7 +776,7 @@ public class NewObjectSnippets implements Snippets {
|
||||
*/
|
||||
initializeObjectHeader(memory, prototypeMarkWord, hub);
|
||||
if (fillContents) {
|
||||
zeroMemory(memory, headerSize, allocationSize, false, maybeUnroll, bulkZeroingStride, counters);
|
||||
zeroMemory(memory, headerSize, allocationSize, false, maybeUnroll, supportsBulkZeroing, counters);
|
||||
} else if (REPLACEMENTS_ASSERTIONS_ENABLED) {
|
||||
fillWithGarbage(memory, headerSize, allocationSize, false, maybeUnroll, counters);
|
||||
}
|
||||
@ -897,7 +897,7 @@ public class NewObjectSnippets implements Snippets {
|
||||
args.addConst("threadRegister", registers.getThreadRegister());
|
||||
args.addConst("maybeUnroll", length.isConstant());
|
||||
args.addConst("typeContext", ProfileAllocations.getValue(localOptions) ? arrayType.toJavaName(false) : "");
|
||||
args.addConst("bulkZeroingStride", tool.getLowerer().bulkZeroingStride());
|
||||
args.addConst("supportsBulkZeroing", tool.getLowerer().supportsBulkZeroing());
|
||||
args.addConst("counters", counters);
|
||||
SnippetTemplate template = template(newArrayNode, args);
|
||||
graph.getDebug().log("Lowering allocateArray in %s: node=%s, template=%s, arguments=%s", graph, newArrayNode, template, args);
|
||||
@ -941,7 +941,7 @@ public class NewObjectSnippets implements Snippets {
|
||||
} else {
|
||||
args.addConst("knownLayoutHelper", 0);
|
||||
}
|
||||
args.addConst("bulkZeroingStride", tool.getLowerer().bulkZeroingStride());
|
||||
args.addConst("supportsBulkZeroing", tool.getLowerer().supportsBulkZeroing());
|
||||
args.add("prototypeMarkWord", lookupArrayClass(tool, JavaKind.Object).prototypeMarkWord());
|
||||
args.addConst("counters", counters);
|
||||
SnippetTemplate template = template(newArrayNode, args);
|
||||
|
@ -26,27 +26,108 @@ package org.graalvm.compiler.java;
|
||||
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.AALOAD;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.AASTORE;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.ACONST_NULL;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.ALOAD;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.ALOAD_0;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.ALOAD_1;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.ALOAD_2;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.ALOAD_3;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.ANEWARRAY;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.ARETURN;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.ARRAYLENGTH;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.ASTORE;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.ASTORE_0;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.ASTORE_1;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.ASTORE_2;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.ASTORE_3;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.ATHROW;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.BALOAD;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.BASTORE;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.BIPUSH;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.BREAKPOINT;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.CALOAD;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.CASTORE;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.CHECKCAST;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.D2F;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.D2I;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.D2L;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.DADD;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.DALOAD;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.DASTORE;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.DCMPG;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.DCMPL;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.DCONST_0;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.DCONST_1;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.DDIV;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.DLOAD;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.DLOAD_0;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.DLOAD_1;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.DLOAD_2;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.DLOAD_3;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.DMUL;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.DNEG;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.DREM;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.DRETURN;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.DSTORE;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.DSTORE_0;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.DSTORE_1;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.DSTORE_2;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.DSTORE_3;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.DSUB;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.DUP;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.DUP2;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.DUP2_X1;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.DUP2_X2;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.DUP_X1;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.DUP_X2;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.F2D;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.F2I;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.F2L;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.FADD;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.FALOAD;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.FASTORE;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.FCMPG;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.FCMPL;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.FCONST_0;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.FCONST_1;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.FCONST_2;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.FDIV;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.FLOAD;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.FLOAD_0;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.FLOAD_1;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.FLOAD_2;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.FLOAD_3;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.FMUL;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.FNEG;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.FREM;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.FRETURN;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.FSTORE;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.FSTORE_0;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.FSTORE_1;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.FSTORE_2;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.FSTORE_3;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.FSUB;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.GETFIELD;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.GETSTATIC;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.GOTO;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.GOTO_W;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.I2B;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.I2C;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.I2D;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.I2F;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.I2L;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.I2S;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.IADD;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.IALOAD;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.IAND;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.IASTORE;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.ICONST_0;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.ICONST_1;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.ICONST_2;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.ICONST_3;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.ICONST_4;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.ICONST_5;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.ICONST_M1;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.IDIV;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.IFEQ;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.IFGE;
|
||||
@ -64,33 +145,88 @@ import static org.graalvm.compiler.bytecode.Bytecodes.IF_ICMPGT;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.IF_ICMPLE;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.IF_ICMPLT;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.IF_ICMPNE;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.IINC;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.ILOAD;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.ILOAD_0;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.ILOAD_1;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.ILOAD_2;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.ILOAD_3;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.IMUL;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.INEG;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.INSTANCEOF;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.INVOKEDYNAMIC;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.INVOKEINTERFACE;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.INVOKESPECIAL;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.INVOKESTATIC;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.INVOKEVIRTUAL;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.IOR;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.IREM;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.IRETURN;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.ISHL;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.ISHR;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.ISTORE;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.ISTORE_0;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.ISTORE_1;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.ISTORE_2;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.ISTORE_3;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.ISUB;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.IUSHR;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.IXOR;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.JSR;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.JSR_W;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.L2D;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.L2F;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.L2I;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.LADD;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.LALOAD;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.LAND;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.LASTORE;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.LCMP;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.LCONST_0;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.LCONST_1;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.LDC;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.LDC2_W;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.LDC_W;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.LDIV;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.LLOAD;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.LLOAD_0;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.LLOAD_1;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.LLOAD_2;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.LLOAD_3;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.LMUL;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.LNEG;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.LOOKUPSWITCH;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.LOR;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.LREM;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.LRETURN;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.LSHL;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.LSHR;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.LSTORE;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.LSTORE_0;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.LSTORE_1;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.LSTORE_2;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.LSTORE_3;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.LSUB;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.LUSHR;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.LXOR;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.MONITORENTER;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.MONITOREXIT;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.MULTIANEWARRAY;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.NEW;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.NEWARRAY;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.NOP;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.POP;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.POP2;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.PUTFIELD;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.PUTSTATIC;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.RET;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.RETURN;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.SALOAD;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.SASTORE;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.SIPUSH;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.SWAP;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.TABLESWITCH;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.WIDE;
|
||||
import static org.graalvm.compiler.core.common.GraalOptions.SupportJsrBytecodes;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
@ -111,6 +247,7 @@ import org.graalvm.compiler.bytecode.BytecodeTableSwitch;
|
||||
import org.graalvm.compiler.bytecode.Bytecodes;
|
||||
import org.graalvm.compiler.core.common.PermanentBailoutException;
|
||||
import org.graalvm.compiler.debug.DebugContext;
|
||||
import org.graalvm.compiler.debug.GraalError;
|
||||
import org.graalvm.compiler.options.OptionValues;
|
||||
|
||||
import jdk.vm.ci.code.BytecodeFrame;
|
||||
@ -159,7 +296,7 @@ public final class BciBlockMapping {
|
||||
|
||||
int id;
|
||||
final int startBci;
|
||||
int endBci;
|
||||
int endBci; // The bci of the last bytecode in the block
|
||||
private boolean isExceptionEntry;
|
||||
private boolean isLoopHeader;
|
||||
int loopId;
|
||||
@ -698,7 +835,9 @@ public final class BciBlockMapping {
|
||||
case SALOAD:
|
||||
case ARRAYLENGTH:
|
||||
case CHECKCAST:
|
||||
case INSTANCEOF:
|
||||
case NEW:
|
||||
case NEWARRAY:
|
||||
case ANEWARRAY:
|
||||
case MULTIANEWARRAY:
|
||||
case PUTSTATIC:
|
||||
@ -707,7 +846,8 @@ public final class BciBlockMapping {
|
||||
case GETFIELD:
|
||||
case LDC:
|
||||
case LDC_W:
|
||||
case LDC2_W: {
|
||||
case LDC2_W:
|
||||
case MONITORENTER: {
|
||||
/*
|
||||
* All bytecodes that can trigger lazy class initialization via a
|
||||
* ClassInitializationPlugin (allocations, static field access) must be listed
|
||||
@ -720,7 +860,150 @@ public final class BciBlockMapping {
|
||||
addSuccessor(blockMap, bci, makeBlock(blockMap, stream.nextBCI()));
|
||||
addSuccessor(blockMap, bci, handler);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case NOP:
|
||||
case ACONST_NULL:
|
||||
case ICONST_M1:
|
||||
case ICONST_0:
|
||||
case ICONST_1:
|
||||
case ICONST_2:
|
||||
case ICONST_3:
|
||||
case ICONST_4:
|
||||
case ICONST_5:
|
||||
case LCONST_0:
|
||||
case LCONST_1:
|
||||
case FCONST_0:
|
||||
case FCONST_1:
|
||||
case FCONST_2:
|
||||
case DCONST_0:
|
||||
case DCONST_1:
|
||||
case BIPUSH:
|
||||
case SIPUSH:
|
||||
case ILOAD:
|
||||
case LLOAD:
|
||||
case FLOAD:
|
||||
case DLOAD:
|
||||
case ALOAD:
|
||||
case ILOAD_0:
|
||||
case ILOAD_1:
|
||||
case ILOAD_2:
|
||||
case ILOAD_3:
|
||||
case LLOAD_0:
|
||||
case LLOAD_1:
|
||||
case LLOAD_2:
|
||||
case LLOAD_3:
|
||||
case FLOAD_0:
|
||||
case FLOAD_1:
|
||||
case FLOAD_2:
|
||||
case FLOAD_3:
|
||||
case DLOAD_0:
|
||||
case DLOAD_1:
|
||||
case DLOAD_2:
|
||||
case DLOAD_3:
|
||||
case ALOAD_0:
|
||||
case ALOAD_1:
|
||||
case ALOAD_2:
|
||||
case ALOAD_3:
|
||||
case ISTORE:
|
||||
case LSTORE:
|
||||
case FSTORE:
|
||||
case DSTORE:
|
||||
case ASTORE:
|
||||
case ISTORE_0:
|
||||
case ISTORE_1:
|
||||
case ISTORE_2:
|
||||
case ISTORE_3:
|
||||
case LSTORE_0:
|
||||
case LSTORE_1:
|
||||
case LSTORE_2:
|
||||
case LSTORE_3:
|
||||
case FSTORE_0:
|
||||
case FSTORE_1:
|
||||
case FSTORE_2:
|
||||
case FSTORE_3:
|
||||
case DSTORE_0:
|
||||
case DSTORE_1:
|
||||
case DSTORE_2:
|
||||
case DSTORE_3:
|
||||
case ASTORE_0:
|
||||
case ASTORE_1:
|
||||
case ASTORE_2:
|
||||
case ASTORE_3:
|
||||
case POP:
|
||||
case POP2:
|
||||
case DUP:
|
||||
case DUP_X1:
|
||||
case DUP_X2:
|
||||
case DUP2:
|
||||
case DUP2_X1:
|
||||
case DUP2_X2:
|
||||
case SWAP:
|
||||
case IADD:
|
||||
case LADD:
|
||||
case FADD:
|
||||
case DADD:
|
||||
case ISUB:
|
||||
case LSUB:
|
||||
case FSUB:
|
||||
case DSUB:
|
||||
case IMUL:
|
||||
case LMUL:
|
||||
case FMUL:
|
||||
case DMUL:
|
||||
case FDIV:
|
||||
case DDIV:
|
||||
case FREM:
|
||||
case DREM:
|
||||
case INEG:
|
||||
case LNEG:
|
||||
case FNEG:
|
||||
case DNEG:
|
||||
case ISHL:
|
||||
case LSHL:
|
||||
case ISHR:
|
||||
case LSHR:
|
||||
case IUSHR:
|
||||
case LUSHR:
|
||||
case IAND:
|
||||
case LAND:
|
||||
case IOR:
|
||||
case LOR:
|
||||
case IXOR:
|
||||
case LXOR:
|
||||
case IINC:
|
||||
case I2L:
|
||||
case I2F:
|
||||
case I2D:
|
||||
case L2I:
|
||||
case L2F:
|
||||
case L2D:
|
||||
case F2I:
|
||||
case F2L:
|
||||
case F2D:
|
||||
case D2I:
|
||||
case D2L:
|
||||
case D2F:
|
||||
case I2B:
|
||||
case I2C:
|
||||
case I2S:
|
||||
case LCMP:
|
||||
case FCMPL:
|
||||
case FCMPG:
|
||||
case DCMPL:
|
||||
case DCMPG:
|
||||
case MONITOREXIT:
|
||||
// All stack manipulation, comparison, conversion and arithmetic operators
|
||||
// except for idiv and irem can't throw exceptions so the don't need to connect
|
||||
// exception edges. MONITOREXIT can't throw exceptions in the context of
|
||||
// compiled code because of the structured locking requirement in the parser.
|
||||
break;
|
||||
|
||||
case WIDE:
|
||||
case BREAKPOINT:
|
||||
default:
|
||||
throw new GraalError("Unhandled bytecode");
|
||||
}
|
||||
stream.next();
|
||||
}
|
||||
|
@ -361,6 +361,7 @@ import org.graalvm.compiler.nodes.calc.CompareNode;
|
||||
import org.graalvm.compiler.nodes.calc.ConditionalNode;
|
||||
import org.graalvm.compiler.nodes.calc.FloatConvertNode;
|
||||
import org.graalvm.compiler.nodes.calc.FloatDivNode;
|
||||
import org.graalvm.compiler.nodes.calc.FloatNormalizeCompareNode;
|
||||
import org.graalvm.compiler.nodes.calc.IntegerBelowNode;
|
||||
import org.graalvm.compiler.nodes.calc.IntegerEqualsNode;
|
||||
import org.graalvm.compiler.nodes.calc.IntegerLessThanNode;
|
||||
@ -370,7 +371,6 @@ import org.graalvm.compiler.nodes.calc.LeftShiftNode;
|
||||
import org.graalvm.compiler.nodes.calc.MulNode;
|
||||
import org.graalvm.compiler.nodes.calc.NarrowNode;
|
||||
import org.graalvm.compiler.nodes.calc.NegateNode;
|
||||
import org.graalvm.compiler.nodes.calc.FloatNormalizeCompareNode;
|
||||
import org.graalvm.compiler.nodes.calc.ObjectEqualsNode;
|
||||
import org.graalvm.compiler.nodes.calc.OrNode;
|
||||
import org.graalvm.compiler.nodes.calc.RemNode;
|
||||
@ -2706,8 +2706,10 @@ public class BytecodeParser implements GraphBuilderContext {
|
||||
}
|
||||
MonitorIdNode monitorId = frameState.peekMonitorId();
|
||||
ValueNode lockedObject = frameState.popLock();
|
||||
if (GraphUtil.originalValue(lockedObject) != GraphUtil.originalValue(x)) {
|
||||
throw bailout(String.format("unbalanced monitors: mismatch at monitorexit, %s != %s", GraphUtil.originalValue(x), GraphUtil.originalValue(lockedObject)));
|
||||
ValueNode originalLockedObject = GraphUtil.originalValue(lockedObject, false);
|
||||
ValueNode originalX = GraphUtil.originalValue(x, false);
|
||||
if (originalLockedObject != originalX) {
|
||||
throw bailout(String.format("unbalanced monitors: mismatch at monitorexit, %s != %s", originalLockedObject, originalX));
|
||||
}
|
||||
MonitorExitNode monitorExit = append(new MonitorExitNode(lockedObject, monitorId, escapedValue));
|
||||
monitorExit.setStateAfter(createFrameState(bci, monitorExit));
|
||||
|
@ -35,6 +35,7 @@ import static org.graalvm.compiler.bytecode.Bytecodes.POP2;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.SWAP;
|
||||
import static org.graalvm.compiler.debug.GraalError.shouldNotReachHere;
|
||||
import static org.graalvm.compiler.nodes.FrameState.TWO_SLOT_MARKER;
|
||||
import static org.graalvm.compiler.nodes.util.GraphUtil.originalValue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@ -70,7 +71,6 @@ import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderTool;
|
||||
import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.SideEffectsState;
|
||||
import org.graalvm.compiler.nodes.graphbuilderconf.ParameterPlugin;
|
||||
import org.graalvm.compiler.nodes.java.MonitorIdNode;
|
||||
import org.graalvm.compiler.nodes.util.GraphUtil;
|
||||
|
||||
import jdk.vm.ci.code.BytecodeFrame;
|
||||
import jdk.vm.ci.meta.Assumptions;
|
||||
@ -384,38 +384,54 @@ public final class FrameStateBuilder implements SideEffectsState {
|
||||
return new FrameStateBuilder(this);
|
||||
}
|
||||
|
||||
public boolean isCompatibleWith(FrameStateBuilder other) {
|
||||
private String incompatibilityErrorMessage(String reason, FrameStateBuilder other) {
|
||||
return String.format("Frame states being merged are incompatible: %s%n This frame state: %s%nOther frame state: %s%nParser context: %s", reason, this, other, parser);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks invariants that must hold when merging {@code other} into this frame state.
|
||||
*
|
||||
* @param other
|
||||
* @throws PermanentBailoutException if the frame states are incompatible with respect to their
|
||||
* locked objects. This indicates bytecode that has unstructured or unbalanced
|
||||
* locks.
|
||||
* @throws GraalError if the frame states are incompatible in terms of {@link #rethrowException}
|
||||
* or stack slots
|
||||
*/
|
||||
public void checkCompatibleWith(FrameStateBuilder other) {
|
||||
assert code.equals(other.code) && graph == other.graph && localsSize() == other.localsSize() : "Can only compare frame states of the same method";
|
||||
assert lockedObjects.length == monitorIds.length && other.lockedObjects.length == other.monitorIds.length : "mismatch between lockedObjects and monitorIds";
|
||||
|
||||
if (rethrowException != other.rethrowException) {
|
||||
return false;
|
||||
throw new GraalError(incompatibilityErrorMessage("mismatch in rethrowException flag", other));
|
||||
}
|
||||
|
||||
if (stackSize() != other.stackSize()) {
|
||||
return false;
|
||||
throw new GraalError(incompatibilityErrorMessage("mismatch in stack sizes", other));
|
||||
}
|
||||
for (int i = 0; i < stackSize(); i++) {
|
||||
ValueNode x = stack[i];
|
||||
ValueNode y = other.stack[i];
|
||||
assert x != null && y != null;
|
||||
if (x != y && (x == TWO_SLOT_MARKER || x.isDeleted() || y == TWO_SLOT_MARKER || y.isDeleted() || x.getStackKind() != y.getStackKind())) {
|
||||
return false;
|
||||
throw new GraalError(incompatibilityErrorMessage("mismatch in stack types", other));
|
||||
}
|
||||
}
|
||||
if (lockedObjects.length != other.lockedObjects.length) {
|
||||
return false;
|
||||
throw new PermanentBailoutException(incompatibilityErrorMessage("unbalanced monitors - locked objects do not match", other));
|
||||
}
|
||||
for (int i = 0; i < lockedObjects.length; i++) {
|
||||
if (GraphUtil.originalValue(lockedObjects[i]) != GraphUtil.originalValue(other.lockedObjects[i]) || monitorIds[i] != other.monitorIds[i]) {
|
||||
throw new PermanentBailoutException("unbalanced monitors");
|
||||
if (originalValue(lockedObjects[i], false) != originalValue(other.lockedObjects[i], false)) {
|
||||
throw new PermanentBailoutException(incompatibilityErrorMessage("unbalanced monitors - locked objects do not match", other));
|
||||
}
|
||||
if (monitorIds[i] != other.monitorIds[i]) {
|
||||
throw new PermanentBailoutException(incompatibilityErrorMessage("unbalanced monitors - monitors do not match", other));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void merge(AbstractMergeNode block, FrameStateBuilder other) {
|
||||
GraalError.guarantee(isCompatibleWith(other), "stacks do not match on merge; bytecodes would not verify:%nexpect: %s%nactual: %s", block, other);
|
||||
checkCompatibleWith(other);
|
||||
|
||||
for (int i = 0; i < localsSize(); i++) {
|
||||
locals[i] = merge(locals[i], other.locals[i], block);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2007, 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
|
||||
@ -24,9 +24,10 @@
|
||||
|
||||
package org.graalvm.compiler.jtt.reflect;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.graalvm.compiler.debug.DebugOptions;
|
||||
import org.graalvm.compiler.jtt.JTTTest;
|
||||
import org.graalvm.compiler.options.OptionValues;
|
||||
import org.junit.Test;
|
||||
|
||||
/*
|
||||
*/
|
||||
@ -76,7 +77,13 @@ public class Field_set02 extends JTTTest {
|
||||
|
||||
@Test
|
||||
public void run0() throws Throwable {
|
||||
runTest("test", 0);
|
||||
try {
|
||||
runTest("test", 0);
|
||||
} catch (AssertionError e) {
|
||||
System.err.println(e);
|
||||
System.err.println("object.byteField == " + object.byteField);
|
||||
runTest(new OptionValues(getInitialOptions(), DebugOptions.Dump, ":2"), "test", 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -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
|
||||
@ -481,7 +481,7 @@ public enum AArch64ArithmeticOp {
|
||||
*/
|
||||
public MultiplyAddSubOp(AArch64ArithmeticOp op, AllocatableValue result, AllocatableValue src1, AllocatableValue src2, AllocatableValue src3) {
|
||||
super(TYPE);
|
||||
assert op == ADD || op == SUB;
|
||||
assert op == ADD || op == SUB || op == FADD;
|
||||
this.op = op;
|
||||
this.result = result;
|
||||
this.src1 = src1;
|
||||
@ -499,6 +499,9 @@ public enum AArch64ArithmeticOp {
|
||||
case SUB:
|
||||
masm.msub(size, asRegister(result), asRegister(src1), asRegister(src2), asRegister(src3));
|
||||
break;
|
||||
case FADD:
|
||||
masm.fmadd(size, asRegister(result), asRegister(src1), asRegister(src2), asRegister(src3));
|
||||
break;
|
||||
default:
|
||||
throw GraalError.shouldNotReachHere();
|
||||
}
|
||||
|
@ -32,6 +32,7 @@ import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
|
||||
import org.graalvm.compiler.asm.Label;
|
||||
import org.graalvm.compiler.asm.aarch64.AArch64Address;
|
||||
import org.graalvm.compiler.asm.aarch64.AArch64Assembler;
|
||||
import org.graalvm.compiler.asm.aarch64.AArch64Assembler.ConditionFlag;
|
||||
import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler;
|
||||
import org.graalvm.compiler.lir.LIRInstructionClass;
|
||||
import org.graalvm.compiler.lir.Opcode;
|
||||
@ -39,7 +40,7 @@ import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
|
||||
|
||||
import jdk.vm.ci.code.CodeUtil;
|
||||
import jdk.vm.ci.code.Register;
|
||||
import jdk.vm.ci.meta.AllocatableValue;
|
||||
import jdk.vm.ci.meta.Value;
|
||||
|
||||
/**
|
||||
* Zero a chunk of memory on AArch64.
|
||||
@ -48,136 +49,186 @@ import jdk.vm.ci.meta.AllocatableValue;
|
||||
public final class AArch64ZeroMemoryOp extends AArch64LIRInstruction {
|
||||
public static final LIRInstructionClass<AArch64ZeroMemoryOp> TYPE = LIRInstructionClass.create(AArch64ZeroMemoryOp.class);
|
||||
|
||||
@Use({REG}) protected AllocatableValue addressValue;
|
||||
@Use({REG}) protected AllocatableValue lengthValue;
|
||||
@Use({REG}) protected Value addressValue;
|
||||
@Use({REG}) protected Value lengthValue;
|
||||
|
||||
@Temp({REG}) protected Value addressValueTemp;
|
||||
@Temp({REG}) protected Value lengthValueTemp;
|
||||
|
||||
private final boolean isAligned;
|
||||
private final boolean useDcZva;
|
||||
private final int zvaLength;
|
||||
|
||||
/**
|
||||
* Constructor of AArch64ZeroMemoryOp.
|
||||
*
|
||||
* @param address allocatable 8-byte aligned base address of the memory chunk.
|
||||
* @param length allocatable length of the memory chunk, the value must be multiple of 8.
|
||||
* @param address starting address of the memory chunk to be zeroed.
|
||||
* @param length size of the memory chunk to be zeroed, in bytes.
|
||||
* @param isAligned whether both address and size are aligned to 8 bytes.
|
||||
* @param useDcZva is DC ZVA instruction is able to use.
|
||||
* @param zvaLength the ZVA length info of current AArch64 CPU, negative value indicates length
|
||||
* is unknown at compile time.
|
||||
*/
|
||||
public AArch64ZeroMemoryOp(AllocatableValue address, AllocatableValue length, boolean useDcZva, int zvaLength) {
|
||||
public AArch64ZeroMemoryOp(Value address, Value length, boolean isAligned, boolean useDcZva, int zvaLength) {
|
||||
super(TYPE);
|
||||
this.addressValue = address;
|
||||
this.lengthValue = length;
|
||||
this.addressValueTemp = address;
|
||||
this.lengthValueTemp = length;
|
||||
this.useDcZva = useDcZva;
|
||||
this.zvaLength = zvaLength;
|
||||
this.isAligned = isAligned;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) {
|
||||
Register base = asRegister(addressValue);
|
||||
Register size = asRegister(lengthValue);
|
||||
if (useDcZva && zvaLength > 0) {
|
||||
// From ARMv8-A architecture reference manual D12.2.35 Data Cache Zero ID register:
|
||||
// A valid ZVA length should be a power-of-2 value in [4, 2048]
|
||||
assert (CodeUtil.isPowerOf2(zvaLength) && 4 <= zvaLength && zvaLength <= 2048);
|
||||
emitZeroMemoryWithDc(masm, base, size, zvaLength);
|
||||
} else {
|
||||
// Use store pair instructions (STP) to zero memory as a fallback.
|
||||
emitZeroMemoryWithStp(masm, base, size);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Zero a chunk of memory with DC ZVA instructions.
|
||||
*
|
||||
* @param masm the AArch64 macro assembler.
|
||||
* @param base base an 8-byte aligned address of the memory chunk to be zeroed.
|
||||
* @param size size of the memory chunk to be zeroed, in bytes, must be multiple of 8.
|
||||
* @param zvaLength the ZVA length info of current AArch64 CPU.
|
||||
*/
|
||||
private static void emitZeroMemoryWithDc(AArch64MacroAssembler masm, Register base, Register size, int zvaLength) {
|
||||
Label preLoop = new Label();
|
||||
Label zvaLoop = new Label();
|
||||
Label postLoop = new Label();
|
||||
Label tail = new Label();
|
||||
Label done = new Label();
|
||||
try (AArch64MacroAssembler.ScratchRegister scratchRegister = masm.getScratchRegister()) {
|
||||
Register alignmentBits = scratchRegister.getRegister();
|
||||
|
||||
try (AArch64MacroAssembler.ScratchRegister sc1 = masm.getScratchRegister()) {
|
||||
Register rscratch1 = sc1.getRegister();
|
||||
Label tail = new Label();
|
||||
Label done = new Label();
|
||||
|
||||
// Count number of bytes to be pre-zeroed to align base address with ZVA length.
|
||||
masm.neg(64, rscratch1, base);
|
||||
masm.and(64, rscratch1, rscratch1, zvaLength - 1);
|
||||
// Jump to DONE if size is zero.
|
||||
masm.cbz(64, size, done);
|
||||
|
||||
// Is size less than number of bytes to be pre-zeroed? Jump to POST_LOOP if so.
|
||||
masm.cmp(64, size, rscratch1);
|
||||
masm.branchConditionally(AArch64Assembler.ConditionFlag.LE, postLoop);
|
||||
masm.sub(64, size, size, rscratch1);
|
||||
if (!isAligned) {
|
||||
Label baseAlignedTo2Bytes = new Label();
|
||||
Label baseAlignedTo4Bytes = new Label();
|
||||
Label baseAlignedTo8Bytes = new Label();
|
||||
|
||||
// Pre-ZVA loop.
|
||||
masm.bind(preLoop);
|
||||
masm.subs(64, rscratch1, rscratch1, 8);
|
||||
masm.branchConditionally(AArch64Assembler.ConditionFlag.LT, zvaLoop);
|
||||
masm.str(64, zr, AArch64Address.createPostIndexedImmediateAddress(base, 8));
|
||||
masm.jmp(preLoop);
|
||||
// Jump to per-byte zeroing loop if the zeroing size is less than 8
|
||||
masm.cmp(64, size, 8);
|
||||
masm.branchConditionally(ConditionFlag.LT, tail);
|
||||
|
||||
// ZVA loop.
|
||||
masm.bind(zvaLoop);
|
||||
masm.subs(64, size, size, zvaLength);
|
||||
masm.branchConditionally(AArch64Assembler.ConditionFlag.LT, tail);
|
||||
masm.dc(AArch64Assembler.DataCacheOperationType.ZVA, base);
|
||||
masm.add(64, base, base, zvaLength);
|
||||
masm.jmp(zvaLoop);
|
||||
// Make base 8-byte aligned
|
||||
masm.neg(64, alignmentBits, base);
|
||||
masm.and(64, alignmentBits, alignmentBits, 7);
|
||||
|
||||
masm.tbz(alignmentBits, 0, baseAlignedTo2Bytes);
|
||||
masm.sub(64, size, size, 1);
|
||||
masm.str(8, zr, AArch64Address.createPostIndexedImmediateAddress(base, 1));
|
||||
masm.bind(baseAlignedTo2Bytes);
|
||||
|
||||
masm.tbz(alignmentBits, 1, baseAlignedTo4Bytes);
|
||||
masm.sub(64, size, size, 2);
|
||||
masm.str(16, zr, AArch64Address.createPostIndexedImmediateAddress(base, 2));
|
||||
masm.bind(baseAlignedTo4Bytes);
|
||||
|
||||
masm.tbz(alignmentBits, 2, baseAlignedTo8Bytes);
|
||||
masm.sub(64, size, size, 4);
|
||||
masm.str(32, zr, AArch64Address.createPostIndexedImmediateAddress(base, 4));
|
||||
masm.bind(baseAlignedTo8Bytes);
|
||||
// At this point base is 8-byte aligned.
|
||||
}
|
||||
|
||||
if (useDcZva && zvaLength > 0) {
|
||||
// From ARMv8-A architecture reference manual D12.2.35 Data Cache Zero ID register:
|
||||
// A valid ZVA length should be a power-of-2 value in [4, 2048]
|
||||
assert (CodeUtil.isPowerOf2(zvaLength) && 4 <= zvaLength && zvaLength <= 2048);
|
||||
|
||||
Label preCheck = new Label();
|
||||
Label preLoop = new Label();
|
||||
Label mainCheck = new Label();
|
||||
Label mainLoop = new Label();
|
||||
Label postCheck = new Label();
|
||||
Label postLoop = new Label();
|
||||
|
||||
masm.neg(64, alignmentBits, base);
|
||||
masm.and(64, alignmentBits, alignmentBits, zvaLength - 1);
|
||||
|
||||
// Is size less than number of bytes to be pre-zeroed? Jump to post check if so.
|
||||
masm.cmp(64, size, alignmentBits);
|
||||
masm.branchConditionally(AArch64Assembler.ConditionFlag.LE, postCheck);
|
||||
masm.sub(64, size, size, alignmentBits);
|
||||
|
||||
// Pre loop: align base according to the supported bulk zeroing stride.
|
||||
masm.jmp(preCheck);
|
||||
|
||||
masm.align(crb.target.wordSize * 2);
|
||||
masm.bind(preLoop);
|
||||
masm.str(64, zr, AArch64Address.createPostIndexedImmediateAddress(base, 8));
|
||||
masm.bind(preCheck);
|
||||
masm.subs(64, alignmentBits, alignmentBits, 8);
|
||||
masm.branchConditionally(AArch64Assembler.ConditionFlag.GE, preLoop);
|
||||
|
||||
// Main loop: bulk zeroing
|
||||
masm.jmp(mainCheck);
|
||||
|
||||
masm.align(crb.target.wordSize * 2);
|
||||
masm.bind(mainLoop);
|
||||
masm.dc(AArch64Assembler.DataCacheOperationType.ZVA, base);
|
||||
masm.add(64, base, base, zvaLength);
|
||||
masm.bind(mainCheck);
|
||||
masm.subs(64, size, size, zvaLength);
|
||||
masm.branchConditionally(AArch64Assembler.ConditionFlag.GE, mainLoop);
|
||||
|
||||
masm.add(64, size, size, zvaLength);
|
||||
|
||||
// Post loop: handle bytes after the main loop
|
||||
masm.jmp(postCheck);
|
||||
|
||||
masm.align(crb.target.wordSize * 2);
|
||||
masm.bind(postLoop);
|
||||
masm.str(64, zr, AArch64Address.createPostIndexedImmediateAddress(base, 8));
|
||||
masm.bind(postCheck);
|
||||
masm.subs(64, size, size, 8);
|
||||
masm.branchConditionally(AArch64Assembler.ConditionFlag.GE, postLoop);
|
||||
|
||||
if (!isAligned) {
|
||||
// Restore size for tail zeroing
|
||||
masm.add(64, size, size, 8);
|
||||
}
|
||||
} else {
|
||||
Label mainCheck = new Label();
|
||||
Label mainLoop = new Label();
|
||||
|
||||
if (!isAligned) {
|
||||
// After aligning base, we may have size less than 8. Need to check again.
|
||||
masm.cmp(64, size, 8);
|
||||
masm.branchConditionally(ConditionFlag.LT, tail);
|
||||
}
|
||||
|
||||
masm.tbz(base, 3, mainCheck);
|
||||
masm.sub(64, size, size, 8);
|
||||
masm.str(64, zr, AArch64Address.createPostIndexedImmediateAddress(base, 8));
|
||||
masm.jmp(mainCheck);
|
||||
|
||||
// The STP loop that zeros 16 bytes in each iteration.
|
||||
masm.align(crb.target.wordSize * 2);
|
||||
masm.bind(mainLoop);
|
||||
masm.stp(64, zr, zr, AArch64Address.createPostIndexedImmediateAddress(base, 2));
|
||||
masm.bind(mainCheck);
|
||||
masm.subs(64, size, size, 16);
|
||||
masm.branchConditionally(AArch64Assembler.ConditionFlag.GE, mainLoop);
|
||||
|
||||
// We may need to zero the tail 8 bytes of the memory chunk.
|
||||
masm.add(64, size, size, 16);
|
||||
masm.tbz(size, 3, tail);
|
||||
masm.str(64, zr, AArch64Address.createPostIndexedImmediateAddress(base, 8));
|
||||
|
||||
if (!isAligned) {
|
||||
// Adjust size for tail zeroing
|
||||
masm.sub(64, size, size, 8);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle bytes after ZVA loop.
|
||||
masm.bind(tail);
|
||||
masm.add(64, size, size, zvaLength);
|
||||
if (!isAligned) {
|
||||
Label perByteZeroingLoop = new Label();
|
||||
|
||||
// Post-ZVA loop.
|
||||
masm.bind(postLoop);
|
||||
masm.subs(64, size, size, 8);
|
||||
masm.branchConditionally(AArch64Assembler.ConditionFlag.LT, done);
|
||||
masm.str(64, zr, AArch64Address.createPostIndexedImmediateAddress(base, 8));
|
||||
masm.jmp(postLoop);
|
||||
|
||||
// Done.
|
||||
masm.cbz(64, size, done);
|
||||
// We have to ensure size > 0 when entering the following loop
|
||||
masm.align(crb.target.wordSize * 2);
|
||||
masm.bind(perByteZeroingLoop);
|
||||
masm.str(8, zr, AArch64Address.createPostIndexedImmediateAddress(base, 1));
|
||||
masm.subs(64, size, size, 1);
|
||||
masm.branchConditionally(AArch64Assembler.ConditionFlag.NE, perByteZeroingLoop);
|
||||
}
|
||||
masm.bind(done);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Zero a chunk of memory with STP instructions.
|
||||
*
|
||||
* @param masm the AArch64 macro assembler.
|
||||
* @param base base an 8-byte aligned address of the memory chunk to be zeroed.
|
||||
* @param size size of the memory chunk to be zeroed, in bytes, must be multiple of 8.
|
||||
*/
|
||||
private static void emitZeroMemoryWithStp(AArch64MacroAssembler masm, Register base, Register size) {
|
||||
Label loop = new Label();
|
||||
Label tail = new Label();
|
||||
Label done = new Label();
|
||||
|
||||
// Jump to DONE if size is zero.
|
||||
masm.cbz(64, size, done);
|
||||
|
||||
// Is base address already 16-byte aligned? Jump to LDP loop if so.
|
||||
masm.tbz(base, 3, loop);
|
||||
masm.sub(64, size, size, 8);
|
||||
masm.str(64, zr, AArch64Address.createPostIndexedImmediateAddress(base, 8));
|
||||
|
||||
// The STP loop that zeros 16 bytes in each iteration.
|
||||
masm.bind(loop);
|
||||
masm.subs(64, size, size, 16);
|
||||
masm.branchConditionally(AArch64Assembler.ConditionFlag.LT, tail);
|
||||
masm.stp(64, zr, zr, AArch64Address.createPostIndexedImmediateAddress(base, 2));
|
||||
masm.jmp(loop);
|
||||
|
||||
// We may need to zero the tail 8 bytes of the memory chunk.
|
||||
masm.bind(tail);
|
||||
masm.adds(64, size, size, 16);
|
||||
masm.branchConditionally(AArch64Assembler.ConditionFlag.EQ, done);
|
||||
masm.str(64, zr, AArch64Address.createPostIndexedImmediateAddress(base, 8));
|
||||
|
||||
// Done.
|
||||
masm.bind(done);
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
@ -115,7 +115,7 @@ import jdk.vm.ci.sparc.SPARCKind;
|
||||
public class SPARCControlFlow {
|
||||
// This describes the maximum offset between the first emitted (load constant in to scratch,
|
||||
// if does not fit into simm5 of cbcond) instruction and the final branch instruction
|
||||
private static final int maximumSelfOffsetInstructions = 2;
|
||||
private static final int maximumSelfOffsetInstructions = 10;
|
||||
|
||||
public static final class ReturnOp extends SPARCBlockEndOp {
|
||||
public static final LIRInstructionClass<ReturnOp> TYPE = LIRInstructionClass.create(ReturnOp.class);
|
||||
|
@ -355,7 +355,7 @@ public interface LIRGeneratorTool extends DiagnosticLIRGeneratorTool, ValueKindF
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
default void emitZeroMemory(Value address, Value length) {
|
||||
default void emitZeroMemory(Value address, Value length, boolean isAligned) {
|
||||
throw GraalError.unimplemented("Bulk zeroing is not implemented on this architecture");
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
@ -245,60 +245,40 @@ public class LoopFragmentInside extends LoopFragment {
|
||||
// Discard the segment entry and its flow, after if merging it into the loop
|
||||
StructuredGraph graph = mainLoopBegin.graph();
|
||||
IfNode loopTest = mainCounted.getLimitTest();
|
||||
IfNode newSegmentTest = getDuplicatedNode(loopTest);
|
||||
AbstractBeginNode trueSuccessor = loopTest.trueSuccessor();
|
||||
AbstractBeginNode falseSuccessor = loopTest.falseSuccessor();
|
||||
FixedNode firstNode;
|
||||
boolean codeInTrueSide = false;
|
||||
if (trueSuccessor == mainCounted.getBody()) {
|
||||
firstNode = trueSuccessor.next();
|
||||
codeInTrueSide = true;
|
||||
} else {
|
||||
assert (falseSuccessor == mainCounted.getBody());
|
||||
firstNode = falseSuccessor.next();
|
||||
}
|
||||
trueSuccessor = newSegmentTest.trueSuccessor();
|
||||
falseSuccessor = newSegmentTest.falseSuccessor();
|
||||
IfNode newSegmentLoopTest = getDuplicatedNode(loopTest);
|
||||
|
||||
// Redirect anchors
|
||||
AbstractBeginNode falseSuccessor = newSegmentLoopTest.falseSuccessor();
|
||||
for (Node usage : falseSuccessor.anchored().snapshot()) {
|
||||
usage.replaceFirstInput(falseSuccessor, loopTest.falseSuccessor());
|
||||
}
|
||||
AbstractBeginNode trueSuccessor = newSegmentLoopTest.trueSuccessor();
|
||||
for (Node usage : trueSuccessor.anchored().snapshot()) {
|
||||
usage.replaceFirstInput(trueSuccessor, loopTest.trueSuccessor());
|
||||
}
|
||||
AbstractBeginNode startBlockNode;
|
||||
if (codeInTrueSide) {
|
||||
startBlockNode = trueSuccessor;
|
||||
} else {
|
||||
graph.getDebug().dump(DebugContext.VERBOSE_LEVEL, mainLoopBegin.graph(), "before");
|
||||
startBlockNode = falseSuccessor;
|
||||
}
|
||||
FixedNode lastNode = getBlockEnd(startBlockNode);
|
||||
LoopEndNode loopEndNode = mainLoopBegin.getSingleLoopEnd();
|
||||
FixedWithNextNode lastCodeNode = (FixedWithNextNode) loopEndNode.predecessor();
|
||||
FixedNode newSegmentFirstNode = getDuplicatedNode(firstNode);
|
||||
FixedWithNextNode newSegmentLastNode = getDuplicatedNode(lastCodeNode);
|
||||
graph.getDebug().dump(DebugContext.DETAILED_LEVEL, loopEndNode.graph(), "Before placing segment");
|
||||
if (firstNode instanceof LoopEndNode) {
|
||||
|
||||
// remove if test
|
||||
graph.removeSplitPropagate(newSegmentLoopTest, loopTest.trueSuccessor() == mainCounted.getBody() ? trueSuccessor : falseSuccessor);
|
||||
|
||||
graph.getDebug().dump(DebugContext.DETAILED_LEVEL, graph, "Before placing segment");
|
||||
if (mainCounted.getBody().next() instanceof LoopEndNode) {
|
||||
GraphUtil.killCFG(getDuplicatedNode(mainLoopBegin));
|
||||
} else {
|
||||
newSegmentLastNode.clearSuccessors();
|
||||
startBlockNode.setNext(lastNode);
|
||||
AbstractBeginNode newSegmentBegin = getDuplicatedNode(mainLoopBegin);
|
||||
FixedNode newSegmentFirstNode = newSegmentBegin.next();
|
||||
EndNode newSegmentEnd = getBlockEnd(newSegmentBegin);
|
||||
FixedWithNextNode newSegmentLastNode = (FixedWithNextNode) newSegmentEnd.predecessor();
|
||||
LoopEndNode loopEndNode = mainLoopBegin.getSingleLoopEnd();
|
||||
FixedWithNextNode lastCodeNode = (FixedWithNextNode) loopEndNode.predecessor();
|
||||
|
||||
newSegmentBegin.clearSuccessors();
|
||||
lastCodeNode.replaceFirstSuccessor(loopEndNode, newSegmentFirstNode);
|
||||
newSegmentLastNode.replaceFirstSuccessor(lastNode, loopEndNode);
|
||||
lastCodeNode.setNext(newSegmentFirstNode);
|
||||
newSegmentLastNode.setNext(loopEndNode);
|
||||
startBlockNode.clearSuccessors();
|
||||
lastNode.safeDelete();
|
||||
Node newSegmentTestStart = newSegmentTest.predecessor();
|
||||
LogicNode newSegmentIfTest = newSegmentTest.condition();
|
||||
newSegmentTestStart.clearSuccessors();
|
||||
newSegmentTest.safeDelete();
|
||||
newSegmentIfTest.safeDelete();
|
||||
trueSuccessor.safeDelete();
|
||||
falseSuccessor.safeDelete();
|
||||
newSegmentTestStart.safeDelete();
|
||||
newSegmentLastNode.replaceFirstSuccessor(newSegmentEnd, loopEndNode);
|
||||
|
||||
newSegmentBegin.safeDelete();
|
||||
newSegmentEnd.safeDelete();
|
||||
}
|
||||
graph.getDebug().dump(DebugContext.DETAILED_LEVEL, loopEndNode.graph(), "After placing segment");
|
||||
graph.getDebug().dump(DebugContext.DETAILED_LEVEL, graph, "After placing segment");
|
||||
}
|
||||
|
||||
private static EndNode getBlockEnd(FixedNode node) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* 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
|
||||
@ -21,11 +21,35 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* JDK 11 and later versioned overlay for the {@code jdk.internal.vm.compiler.management} module.
|
||||
* This cannot be used in JDK 10 where {@code jdk.internal.vm.compiler.management} is a
|
||||
* non-upgradeable module.
|
||||
*/
|
||||
|
||||
package org.graalvm.compiler.nodes.test;
|
||||
|
||||
package org.graalvm.compiler.hotspot.management;
|
||||
import static org.graalvm.compiler.java.BytecodeParserOptions.InlineDuringParsing;
|
||||
|
||||
import org.graalvm.compiler.core.phases.HighTier;
|
||||
import org.graalvm.compiler.core.test.GraalCompilerTest;
|
||||
import org.graalvm.compiler.options.OptionValues;
|
||||
import org.junit.Test;
|
||||
|
||||
public class ExceptionLivenessTest extends GraalCompilerTest {
|
||||
@Test
|
||||
public void testNewarray() {
|
||||
OptionValues options = new OptionValues(getInitialOptions(), HighTier.Options.Inline, false, InlineDuringParsing, false);
|
||||
test(options, "newarraySnippet");
|
||||
}
|
||||
|
||||
public static int[] newarraySnippet() {
|
||||
int[] array = new int[4];
|
||||
|
||||
dummy();
|
||||
try {
|
||||
array = new int[-10];
|
||||
} catch (NegativeArraySizeException exc3) {
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
@BytecodeParserNeverInline
|
||||
static void dummy() {
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 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
|
||||
@ -32,6 +32,7 @@ import org.graalvm.compiler.core.common.type.StampFactory;
|
||||
import org.graalvm.compiler.graph.IterableNodeType;
|
||||
import org.graalvm.compiler.graph.Node;
|
||||
import org.graalvm.compiler.graph.NodeClass;
|
||||
import org.graalvm.compiler.graph.Position;
|
||||
import org.graalvm.compiler.graph.iterators.NodeIterable;
|
||||
import org.graalvm.compiler.nodeinfo.InputType;
|
||||
import org.graalvm.compiler.nodeinfo.NodeInfo;
|
||||
@ -97,6 +98,19 @@ public abstract class AbstractBeginNode extends FixedWithNextNode implements LIR
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isUsedAsGuardInput() {
|
||||
if (this.hasUsages()) {
|
||||
for (Node n : usages()) {
|
||||
for (Position inputPosition : n.inputPositions()) {
|
||||
if (inputPosition.getInputType() == InputType.Guard && inputPosition.get(n) == this) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public NodeIterable<GuardNode> guards() {
|
||||
return usages().filter(GuardNode.class);
|
||||
}
|
||||
@ -105,6 +119,10 @@ public abstract class AbstractBeginNode extends FixedWithNextNode implements LIR
|
||||
return usages();
|
||||
}
|
||||
|
||||
public boolean hasAnchored() {
|
||||
return this.hasUsages();
|
||||
}
|
||||
|
||||
public NodeIterable<FixedNode> getBlockNodes() {
|
||||
return new NodeIterable<FixedNode>() {
|
||||
|
||||
|
@ -548,7 +548,7 @@ public final class IfNode extends ControlSplitNode implements Simplifiable, LIRL
|
||||
return false;
|
||||
}
|
||||
|
||||
if (trueSuccessor().anchored().isNotEmpty() || falseSuccessor().anchored().isNotEmpty()) {
|
||||
if (trueSuccessor().hasAnchored() || falseSuccessor().hasAnchored()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1216,6 +1216,10 @@ public final class IfNode extends ControlSplitNode implements Simplifiable, LIRL
|
||||
return false;
|
||||
}
|
||||
|
||||
if (trueSuccessor().isUsedAsGuardInput() || falseSuccessor().isUsedAsGuardInput()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ValuePhiNode phi = (ValuePhiNode) generalPhi;
|
||||
|
||||
EconomicMap<Node, NodeColor> coloredNodes = EconomicMap.create(Equivalence.IDENTITY, 8);
|
||||
@ -1645,6 +1649,10 @@ public final class IfNode extends ControlSplitNode implements Simplifiable, LIRL
|
||||
return false;
|
||||
}
|
||||
|
||||
if (trueSuccessor().isUsedAsGuardInput() || falseSuccessor().isUsedAsGuardInput()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Ensure phi is used by at most the comparison and the merge's frame state (if any)
|
||||
ValuePhiNode phi = (ValuePhiNode) singleUsage;
|
||||
NodeIterable<Node> phiUsages = phi.usages();
|
||||
|
@ -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
|
||||
@ -26,8 +26,10 @@ package org.graalvm.compiler.nodes.calc;
|
||||
|
||||
import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_2;
|
||||
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1;
|
||||
import static org.graalvm.compiler.nodes.calc.BinaryArithmeticNode.getArithmeticOpTable;
|
||||
|
||||
import org.graalvm.compiler.core.common.type.ArithmeticOpTable;
|
||||
import org.graalvm.compiler.core.common.type.ArithmeticOpTable.UnaryOp;
|
||||
import org.graalvm.compiler.core.common.type.ArithmeticOpTable.UnaryOp.Abs;
|
||||
import org.graalvm.compiler.graph.NodeClass;
|
||||
import org.graalvm.compiler.graph.spi.CanonicalizerTool;
|
||||
@ -46,7 +48,7 @@ public final class AbsNode extends UnaryArithmeticNode<Abs> implements Arithmeti
|
||||
public static final NodeClass<AbsNode> TYPE = NodeClass.create(AbsNode.class);
|
||||
|
||||
public AbsNode(ValueNode x) {
|
||||
super(TYPE, ArithmeticOpTable::getAbs, x);
|
||||
super(TYPE, getArithmeticOpTable(x).getAbs(), x);
|
||||
}
|
||||
|
||||
public static ValueNode create(ValueNode value, NodeView view) {
|
||||
@ -66,6 +68,11 @@ public final class AbsNode extends UnaryArithmeticNode<Abs> implements Arithmeti
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected UnaryOp<Abs> getOp(ArithmeticOpTable table) {
|
||||
return table.getAbs();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) {
|
||||
ValueNode ret = super.canonical(tool, forValue);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 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 AddNode extends BinaryArithmeticNode<Add> implements NarrowableArit
|
||||
}
|
||||
|
||||
protected AddNode(NodeClass<? extends AddNode> c, ValueNode x, ValueNode y) {
|
||||
super(c, ArithmeticOpTable::getAdd, x, y);
|
||||
super(c, getArithmeticOpTable(x).getAdd(), x, y);
|
||||
}
|
||||
|
||||
public static ValueNode create(ValueNode x, ValueNode y, NodeView view) {
|
||||
@ -71,6 +71,11 @@ public class AddNode extends BinaryArithmeticNode<Add> implements NarrowableArit
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BinaryOp<Add> getOp(ArithmeticOpTable table) {
|
||||
return table.getAdd();
|
||||
}
|
||||
|
||||
private static ValueNode canonical(AddNode addNode, BinaryOp<Add> op, ValueNode forX, ValueNode forY, NodeView view) {
|
||||
AddNode self = addNode;
|
||||
boolean associative = op.isAssociative();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 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
|
||||
@ -51,7 +51,7 @@ public final class AndNode extends BinaryArithmeticNode<And> implements Narrowab
|
||||
public static final NodeClass<AndNode> TYPE = NodeClass.create(AndNode.class);
|
||||
|
||||
public AndNode(ValueNode x, ValueNode y) {
|
||||
super(TYPE, ArithmeticOpTable::getAnd, x, y);
|
||||
super(TYPE, getArithmeticOpTable(x).getAnd(), x, y);
|
||||
}
|
||||
|
||||
public static ValueNode create(ValueNode x, ValueNode y, NodeView view) {
|
||||
@ -64,6 +64,11 @@ public final class AndNode extends BinaryArithmeticNode<And> implements Narrowab
|
||||
return canonical(null, op, stamp, x, y, view);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BinaryOp<And> getOp(ArithmeticOpTable table) {
|
||||
return table.getAnd();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
|
||||
ValueNode ret = super.canonical(tool, forX, forY);
|
||||
|
@ -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
|
||||
@ -27,9 +27,6 @@ package org.graalvm.compiler.nodes.calc;
|
||||
import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_1;
|
||||
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.graalvm.compiler.core.common.type.ArithmeticOpTable;
|
||||
import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp;
|
||||
import org.graalvm.compiler.core.common.type.IntegerStamp;
|
||||
@ -58,20 +55,20 @@ public abstract class BinaryArithmeticNode<OP> extends BinaryNode implements Ari
|
||||
|
||||
@SuppressWarnings("rawtypes") public static final NodeClass<BinaryArithmeticNode> TYPE = NodeClass.create(BinaryArithmeticNode.class);
|
||||
|
||||
protected interface SerializableBinaryFunction<T> extends Function<ArithmeticOpTable, BinaryOp<T>>, Serializable {
|
||||
protected BinaryArithmeticNode(NodeClass<? extends BinaryArithmeticNode<OP>> c, BinaryOp<OP> opForStampComputation, ValueNode x, ValueNode y) {
|
||||
super(c, opForStampComputation.foldStamp(x.stamp(NodeView.DEFAULT), y.stamp(NodeView.DEFAULT)), x, y);
|
||||
}
|
||||
|
||||
protected final SerializableBinaryFunction<OP> getOp;
|
||||
|
||||
protected BinaryArithmeticNode(NodeClass<? extends BinaryArithmeticNode<OP>> c, SerializableBinaryFunction<OP> getOp, ValueNode x, ValueNode y) {
|
||||
super(c, getOp.apply(ArithmeticOpTable.forStamp(x.stamp(NodeView.DEFAULT))).foldStamp(x.stamp(NodeView.DEFAULT), y.stamp(NodeView.DEFAULT)), x, y);
|
||||
this.getOp = getOp;
|
||||
public static ArithmeticOpTable getArithmeticOpTable(ValueNode forValue) {
|
||||
return ArithmeticOpTable.forStamp(forValue.stamp(NodeView.DEFAULT));
|
||||
}
|
||||
|
||||
protected abstract BinaryOp<OP> getOp(ArithmeticOpTable table);
|
||||
|
||||
protected final BinaryOp<OP> getOp(ValueNode forX, ValueNode forY) {
|
||||
ArithmeticOpTable table = ArithmeticOpTable.forStamp(forX.stamp(NodeView.DEFAULT));
|
||||
assert table.equals(ArithmeticOpTable.forStamp(forY.stamp(NodeView.DEFAULT)));
|
||||
return getOp.apply(table);
|
||||
ArithmeticOpTable table = getArithmeticOpTable(forX);
|
||||
assert table.equals(getArithmeticOpTable(forY));
|
||||
return getOp(table);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 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,12 @@
|
||||
package org.graalvm.compiler.nodes.calc;
|
||||
|
||||
import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_8;
|
||||
|
||||
import java.util.EnumMap;
|
||||
import static org.graalvm.compiler.nodes.calc.BinaryArithmeticNode.getArithmeticOpTable;
|
||||
|
||||
import org.graalvm.compiler.core.common.calc.FloatConvert;
|
||||
import org.graalvm.compiler.core.common.type.ArithmeticOpTable;
|
||||
import org.graalvm.compiler.core.common.type.ArithmeticOpTable.FloatConvertOp;
|
||||
import org.graalvm.compiler.core.common.type.ArithmeticOpTable.UnaryOp;
|
||||
import org.graalvm.compiler.graph.NodeClass;
|
||||
import org.graalvm.compiler.graph.spi.CanonicalizerTool;
|
||||
import org.graalvm.compiler.lir.gen.ArithmeticLIRGeneratorTool;
|
||||
@ -55,16 +55,8 @@ public final class FloatConvertNode extends UnaryArithmeticNode<FloatConvertOp>
|
||||
|
||||
protected final FloatConvert op;
|
||||
|
||||
private static final EnumMap<FloatConvert, SerializableUnaryFunction<FloatConvertOp>> getOps;
|
||||
static {
|
||||
getOps = new EnumMap<>(FloatConvert.class);
|
||||
for (FloatConvert op : FloatConvert.values()) {
|
||||
getOps.put(op, table -> table.getFloatConvert(op));
|
||||
}
|
||||
}
|
||||
|
||||
public FloatConvertNode(FloatConvert op, ValueNode input) {
|
||||
super(TYPE, getOps.get(op), input);
|
||||
super(TYPE, getArithmeticOpTable(input).getFloatConvert(op), input);
|
||||
this.op = op;
|
||||
}
|
||||
|
||||
@ -76,6 +68,11 @@ public final class FloatConvertNode extends UnaryArithmeticNode<FloatConvertOp>
|
||||
return new FloatConvertNode(op, input);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected UnaryOp<FloatConvertOp> getOp(ArithmeticOpTable table) {
|
||||
return table.getFloatConvert(op);
|
||||
}
|
||||
|
||||
public FloatConvert getFloatConvert() {
|
||||
return op;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 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
|
||||
@ -52,7 +52,7 @@ public class FloatDivNode extends BinaryArithmeticNode<Div> {
|
||||
}
|
||||
|
||||
protected FloatDivNode(NodeClass<? extends FloatDivNode> c, ValueNode x, ValueNode y) {
|
||||
super(c, ArithmeticOpTable::getDiv, x, y);
|
||||
super(c, getArithmeticOpTable(x).getDiv(), x, y);
|
||||
assert stamp instanceof FloatStamp;
|
||||
}
|
||||
|
||||
@ -66,6 +66,11 @@ public class FloatDivNode extends BinaryArithmeticNode<Div> {
|
||||
return canonical(null, op, x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BinaryOp<Div> getOp(ArithmeticOpTable table) {
|
||||
return table.getDiv();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
|
||||
ValueNode ret = super.canonical(tool, forX, forY);
|
||||
|
@ -24,8 +24,7 @@
|
||||
|
||||
package org.graalvm.compiler.nodes.calc;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.function.Function;
|
||||
import static org.graalvm.compiler.nodes.calc.BinaryArithmeticNode.getArithmeticOpTable;
|
||||
|
||||
import org.graalvm.compiler.core.common.type.ArithmeticOpTable;
|
||||
import org.graalvm.compiler.core.common.type.ArithmeticOpTable.IntegerConvertOp;
|
||||
@ -53,20 +52,11 @@ import jdk.vm.ci.meta.ConstantReflectionProvider;
|
||||
public abstract class IntegerConvertNode<OP, REV> extends UnaryNode implements ArithmeticOperation, ConvertNode, ArithmeticLIRLowerable, StampInverter {
|
||||
@SuppressWarnings("rawtypes") public static final NodeClass<IntegerConvertNode> TYPE = NodeClass.create(IntegerConvertNode.class);
|
||||
|
||||
protected final SerializableIntegerConvertFunction<OP> getOp;
|
||||
protected final SerializableIntegerConvertFunction<REV> getReverseOp;
|
||||
|
||||
protected final int inputBits;
|
||||
protected final int resultBits;
|
||||
|
||||
protected interface SerializableIntegerConvertFunction<T> extends Function<ArithmeticOpTable, IntegerConvertOp<T>>, Serializable {
|
||||
}
|
||||
|
||||
protected IntegerConvertNode(NodeClass<? extends IntegerConvertNode<OP, REV>> c, SerializableIntegerConvertFunction<OP> getOp, SerializableIntegerConvertFunction<REV> getReverseOp, int inputBits,
|
||||
int resultBits, ValueNode input) {
|
||||
super(c, getOp.apply(ArithmeticOpTable.forStamp(input.stamp(NodeView.DEFAULT))).foldStamp(inputBits, resultBits, input.stamp(NodeView.DEFAULT)), input);
|
||||
this.getOp = getOp;
|
||||
this.getReverseOp = getReverseOp;
|
||||
protected IntegerConvertNode(NodeClass<? extends IntegerConvertNode<OP, REV>> c, IntegerConvertOp<OP> opForStampComputation, int inputBits, int resultBits, ValueNode input) {
|
||||
super(c, opForStampComputation.foldStamp(inputBits, resultBits, input.stamp(NodeView.DEFAULT)), input);
|
||||
this.inputBits = inputBits;
|
||||
this.resultBits = resultBits;
|
||||
assert PrimitiveStamp.getBits(input.stamp(NodeView.DEFAULT)) == 0 || PrimitiveStamp.getBits(input.stamp(NodeView.DEFAULT)) == inputBits;
|
||||
@ -80,13 +70,13 @@ public abstract class IntegerConvertNode<OP, REV> extends UnaryNode implements A
|
||||
return resultBits;
|
||||
}
|
||||
|
||||
protected final IntegerConvertOp<OP> getOp(ValueNode forValue) {
|
||||
return getOp.apply(ArithmeticOpTable.forStamp(forValue.stamp(NodeView.DEFAULT)));
|
||||
}
|
||||
protected abstract IntegerConvertOp<OP> getOp(ArithmeticOpTable table);
|
||||
|
||||
protected abstract IntegerConvertOp<REV> getReverseOp(ArithmeticOpTable table);
|
||||
|
||||
@Override
|
||||
public final IntegerConvertOp<OP> getArithmeticOp() {
|
||||
return getOp(getValue());
|
||||
return getOp(getArithmeticOpTable(getValue()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -96,7 +86,7 @@ public abstract class IntegerConvertNode<OP, REV> extends UnaryNode implements A
|
||||
|
||||
@Override
|
||||
public Constant reverse(Constant c, ConstantReflectionProvider constantReflection) {
|
||||
IntegerConvertOp<REV> reverse = getReverseOp.apply(ArithmeticOpTable.forStamp(stamp(NodeView.DEFAULT)));
|
||||
IntegerConvertOp<REV> reverse = getReverseOp(ArithmeticOpTable.forStamp(stamp(NodeView.DEFAULT)));
|
||||
return reverse.foldConstant(getResultBits(), getInputBits(), c);
|
||||
}
|
||||
|
||||
@ -108,7 +98,7 @@ public abstract class IntegerConvertNode<OP, REV> extends UnaryNode implements A
|
||||
|
||||
@Override
|
||||
public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) {
|
||||
ValueNode synonym = findSynonym(getOp(forValue), forValue, inputBits, resultBits, stamp(NodeView.DEFAULT));
|
||||
ValueNode synonym = findSynonym(getOp(getArithmeticOpTable(forValue)), forValue, inputBits, resultBits, stamp(NodeView.DEFAULT));
|
||||
if (synonym != null) {
|
||||
return synonym;
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_2;
|
||||
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_2;
|
||||
|
||||
import org.graalvm.compiler.core.common.type.ArithmeticOpTable;
|
||||
import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp;
|
||||
import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp.MulHigh;
|
||||
import org.graalvm.compiler.graph.NodeClass;
|
||||
import org.graalvm.compiler.graph.spi.Canonicalizable;
|
||||
@ -48,7 +49,12 @@ public final class IntegerMulHighNode extends BinaryArithmeticNode<MulHigh> impl
|
||||
public static final NodeClass<IntegerMulHighNode> TYPE = NodeClass.create(IntegerMulHighNode.class);
|
||||
|
||||
public IntegerMulHighNode(ValueNode x, ValueNode y) {
|
||||
super(TYPE, ArithmeticOpTable::getMulHigh, x, y);
|
||||
super(TYPE, getArithmeticOpTable(x).getMulHigh(), x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BinaryOp<MulHigh> getOp(ArithmeticOpTable table) {
|
||||
return table.getMulHigh();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 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
|
||||
@ -24,7 +24,10 @@
|
||||
|
||||
package org.graalvm.compiler.nodes.calc;
|
||||
|
||||
import static org.graalvm.compiler.nodes.calc.BinaryArithmeticNode.getArithmeticOpTable;
|
||||
|
||||
import org.graalvm.compiler.core.common.type.ArithmeticOpTable;
|
||||
import org.graalvm.compiler.core.common.type.ArithmeticOpTable.ShiftOp;
|
||||
import org.graalvm.compiler.core.common.type.ArithmeticOpTable.ShiftOp.Shl;
|
||||
import org.graalvm.compiler.core.common.type.IntegerStamp;
|
||||
import org.graalvm.compiler.core.common.type.Stamp;
|
||||
@ -45,7 +48,7 @@ public final class LeftShiftNode extends ShiftNode<Shl> {
|
||||
public static final NodeClass<LeftShiftNode> TYPE = NodeClass.create(LeftShiftNode.class);
|
||||
|
||||
public LeftShiftNode(ValueNode x, ValueNode y) {
|
||||
super(TYPE, ArithmeticOpTable::getShl, x, y);
|
||||
super(TYPE, getArithmeticOpTable(x).getShl(), x, y);
|
||||
}
|
||||
|
||||
public static ValueNode create(ValueNode x, ValueNode y, NodeView view) {
|
||||
@ -59,6 +62,11 @@ public final class LeftShiftNode extends ShiftNode<Shl> {
|
||||
return canonical(null, op, stamp, x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ShiftOp<Shl> getOp(ArithmeticOpTable table) {
|
||||
return table.getShl();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
|
||||
ValueNode ret = super.canonical(tool, forX, forY);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 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
|
||||
@ -27,9 +27,9 @@ package org.graalvm.compiler.nodes.calc;
|
||||
import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_2;
|
||||
|
||||
import org.graalvm.compiler.core.common.type.ArithmeticOpTable;
|
||||
import org.graalvm.compiler.core.common.type.IntegerStamp;
|
||||
import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp;
|
||||
import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp.Mul;
|
||||
import org.graalvm.compiler.core.common.type.IntegerStamp;
|
||||
import org.graalvm.compiler.core.common.type.Stamp;
|
||||
import org.graalvm.compiler.graph.NodeClass;
|
||||
import org.graalvm.compiler.graph.spi.Canonicalizable.BinaryCommutative;
|
||||
@ -56,7 +56,7 @@ public class MulNode extends BinaryArithmeticNode<Mul> implements NarrowableArit
|
||||
}
|
||||
|
||||
protected MulNode(NodeClass<? extends MulNode> c, ValueNode x, ValueNode y) {
|
||||
super(c, ArithmeticOpTable::getMul, x, y);
|
||||
super(c, getArithmeticOpTable(x).getMul(), x, y);
|
||||
}
|
||||
|
||||
public static ValueNode create(ValueNode x, ValueNode y, NodeView view) {
|
||||
@ -69,6 +69,11 @@ public class MulNode extends BinaryArithmeticNode<Mul> implements NarrowableArit
|
||||
return canonical(null, op, stamp, x, y, view);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BinaryOp<Mul> getOp(ArithmeticOpTable table) {
|
||||
return table.getMul();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
|
||||
ValueNode ret = super.canonical(tool, forX, forY);
|
||||
|
@ -25,6 +25,7 @@
|
||||
package org.graalvm.compiler.nodes.calc;
|
||||
|
||||
import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_1;
|
||||
import static org.graalvm.compiler.nodes.calc.BinaryArithmeticNode.getArithmeticOpTable;
|
||||
|
||||
import org.graalvm.compiler.core.common.calc.CanonicalCondition;
|
||||
import org.graalvm.compiler.core.common.type.ArithmeticOpTable;
|
||||
@ -58,7 +59,7 @@ public final class NarrowNode extends IntegerConvertNode<Narrow, SignExtend> {
|
||||
}
|
||||
|
||||
public NarrowNode(ValueNode input, int inputBits, int resultBits) {
|
||||
super(TYPE, ArithmeticOpTable::getNarrow, ArithmeticOpTable::getSignExtend, inputBits, resultBits, input);
|
||||
super(TYPE, getArithmeticOpTable(input).getNarrow(), inputBits, resultBits, input);
|
||||
}
|
||||
|
||||
public static ValueNode create(ValueNode input, int resultBits, NodeView view) {
|
||||
@ -75,6 +76,16 @@ public final class NarrowNode extends IntegerConvertNode<Narrow, SignExtend> {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IntegerConvertOp<Narrow> getOp(ArithmeticOpTable table) {
|
||||
return table.getNarrow();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IntegerConvertOp<SignExtend> getReverseOp(ArithmeticOpTable table) {
|
||||
return table.getSignExtend();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLossless() {
|
||||
return checkLossless(this.getResultBits());
|
||||
|
@ -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
|
||||
@ -26,8 +26,10 @@ package org.graalvm.compiler.nodes.calc;
|
||||
|
||||
import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_2;
|
||||
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1;
|
||||
import static org.graalvm.compiler.nodes.calc.BinaryArithmeticNode.getArithmeticOpTable;
|
||||
|
||||
import org.graalvm.compiler.core.common.type.ArithmeticOpTable;
|
||||
import org.graalvm.compiler.core.common.type.ArithmeticOpTable.UnaryOp;
|
||||
import org.graalvm.compiler.core.common.type.ArithmeticOpTable.UnaryOp.Neg;
|
||||
import org.graalvm.compiler.core.common.type.FloatStamp;
|
||||
import org.graalvm.compiler.core.common.type.Stamp;
|
||||
@ -49,7 +51,7 @@ public final class NegateNode extends UnaryArithmeticNode<Neg> implements Narrow
|
||||
public static final NodeClass<NegateNode> TYPE = NodeClass.create(NegateNode.class);
|
||||
|
||||
public NegateNode(ValueNode value) {
|
||||
super(TYPE, ArithmeticOpTable::getNeg, value);
|
||||
super(TYPE, getArithmeticOpTable(value).getNeg(), value);
|
||||
}
|
||||
|
||||
public static ValueNode create(ValueNode value, NodeView view) {
|
||||
@ -60,6 +62,11 @@ public final class NegateNode extends UnaryArithmeticNode<Neg> implements Narrow
|
||||
return new NegateNode(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected UnaryOp<Neg> getOp(ArithmeticOpTable table) {
|
||||
return table.getNeg();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) {
|
||||
ValueNode synonym = findSynonym(forValue, getOp(forValue));
|
||||
|
@ -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
|
||||
@ -26,8 +26,10 @@ package org.graalvm.compiler.nodes.calc;
|
||||
|
||||
import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_1;
|
||||
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1;
|
||||
import static org.graalvm.compiler.nodes.calc.BinaryArithmeticNode.getArithmeticOpTable;
|
||||
|
||||
import org.graalvm.compiler.core.common.type.ArithmeticOpTable;
|
||||
import org.graalvm.compiler.core.common.type.ArithmeticOpTable.UnaryOp;
|
||||
import org.graalvm.compiler.core.common.type.ArithmeticOpTable.UnaryOp.Not;
|
||||
import org.graalvm.compiler.core.common.type.Stamp;
|
||||
import org.graalvm.compiler.graph.NodeClass;
|
||||
@ -48,13 +50,18 @@ public final class NotNode extends UnaryArithmeticNode<Not> implements Arithmeti
|
||||
public static final NodeClass<NotNode> TYPE = NodeClass.create(NotNode.class);
|
||||
|
||||
protected NotNode(ValueNode x) {
|
||||
super(TYPE, ArithmeticOpTable::getNot, x);
|
||||
super(TYPE, getArithmeticOpTable(x).getNot(), x);
|
||||
}
|
||||
|
||||
public static ValueNode create(ValueNode x) {
|
||||
return canonicalize(null, x);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected UnaryOp<Not> getOp(ArithmeticOpTable table) {
|
||||
return table.getNot();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) {
|
||||
ValueNode ret = super.canonical(tool, forValue);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 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
|
||||
@ -39,10 +39,13 @@ import org.graalvm.compiler.nodes.LogicNode;
|
||||
import org.graalvm.compiler.nodes.NodeView;
|
||||
import org.graalvm.compiler.nodes.StructuredGraph;
|
||||
import org.graalvm.compiler.nodes.ValueNode;
|
||||
import org.graalvm.compiler.nodes.extended.BoxNode;
|
||||
import org.graalvm.compiler.nodes.extended.GetClassNode;
|
||||
import org.graalvm.compiler.nodes.java.AbstractNewObjectNode;
|
||||
import org.graalvm.compiler.nodes.java.InstanceOfNode;
|
||||
import org.graalvm.compiler.nodes.spi.Virtualizable;
|
||||
import org.graalvm.compiler.nodes.spi.VirtualizerTool;
|
||||
import org.graalvm.compiler.nodes.virtual.AllocatedObjectNode;
|
||||
import org.graalvm.compiler.nodes.virtual.VirtualBoxingNode;
|
||||
import org.graalvm.compiler.nodes.virtual.VirtualObjectNode;
|
||||
import org.graalvm.compiler.options.OptionValues;
|
||||
@ -112,6 +115,11 @@ public final class ObjectEqualsNode extends PointerEqualsNode implements Virtual
|
||||
}
|
||||
return LogicConstantNode.forBoolean(false);
|
||||
}
|
||||
if (nonConstant instanceof AbstractNewObjectNode || nonConstant instanceof AllocatedObjectNode) {
|
||||
assert !(nonConstant instanceof BoxNode); // guard against class hierarchy changes
|
||||
// a constant can never be equals to a new object
|
||||
return LogicConstantNode.forBoolean(false);
|
||||
}
|
||||
return super.canonicalizeSymmetricConstant(constantReflection, metaAccess, options, smallestCompareWidth, condition, constant, nonConstant, mirrored, unorderedIsTrue, view);
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 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,7 +50,7 @@ public final class OrNode extends BinaryArithmeticNode<Or> implements BinaryComm
|
||||
public static final NodeClass<OrNode> TYPE = NodeClass.create(OrNode.class);
|
||||
|
||||
public OrNode(ValueNode x, ValueNode y) {
|
||||
super(TYPE, ArithmeticOpTable::getOr, x, y);
|
||||
super(TYPE, getArithmeticOpTable(x).getOr(), x, y);
|
||||
}
|
||||
|
||||
public static ValueNode create(ValueNode x, ValueNode y, NodeView view) {
|
||||
@ -63,6 +63,11 @@ public final class OrNode extends BinaryArithmeticNode<Or> implements BinaryComm
|
||||
return canonical(null, op, stamp, x, y, view);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BinaryOp<Or> getOp(ArithmeticOpTable table) {
|
||||
return table.getOr();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
|
||||
NodeView view = NodeView.from(tool);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 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,7 +50,7 @@ public class RemNode extends BinaryArithmeticNode<Rem> implements Lowerable {
|
||||
}
|
||||
|
||||
protected RemNode(NodeClass<? extends RemNode> c, ValueNode x, ValueNode y) {
|
||||
super(c, ArithmeticOpTable::getRem, x, y);
|
||||
super(c, getArithmeticOpTable(x).getRem(), x, y);
|
||||
}
|
||||
|
||||
public static ValueNode create(ValueNode forX, ValueNode forY, NodeView view) {
|
||||
@ -63,6 +63,11 @@ public class RemNode extends BinaryArithmeticNode<Rem> implements Lowerable {
|
||||
return new RemNode(forX, forY);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BinaryOp<Rem> getOp(ArithmeticOpTable table) {
|
||||
return table.getRem();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void lower(LoweringTool tool) {
|
||||
tool.getLowerer().lower(this, tool);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 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
|
||||
@ -24,7 +24,10 @@
|
||||
|
||||
package org.graalvm.compiler.nodes.calc;
|
||||
|
||||
import static org.graalvm.compiler.nodes.calc.BinaryArithmeticNode.getArithmeticOpTable;
|
||||
|
||||
import org.graalvm.compiler.core.common.type.ArithmeticOpTable;
|
||||
import org.graalvm.compiler.core.common.type.ArithmeticOpTable.ShiftOp;
|
||||
import org.graalvm.compiler.core.common.type.ArithmeticOpTable.ShiftOp.Shr;
|
||||
import org.graalvm.compiler.core.common.type.IntegerStamp;
|
||||
import org.graalvm.compiler.core.common.type.Stamp;
|
||||
@ -45,7 +48,7 @@ public final class RightShiftNode extends ShiftNode<Shr> {
|
||||
public static final NodeClass<RightShiftNode> TYPE = NodeClass.create(RightShiftNode.class);
|
||||
|
||||
public RightShiftNode(ValueNode x, ValueNode y) {
|
||||
super(TYPE, ArithmeticOpTable::getShr, x, y);
|
||||
super(TYPE, getArithmeticOpTable(x).getShr(), x, y);
|
||||
}
|
||||
|
||||
public static ValueNode create(ValueNode x, int y, NodeView view) {
|
||||
@ -66,6 +69,11 @@ public final class RightShiftNode extends ShiftNode<Shr> {
|
||||
return canonical(null, op, stamp, x, y, view);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ShiftOp<Shr> getOp(ArithmeticOpTable table) {
|
||||
return table.getShr();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
|
||||
NodeView view = NodeView.from(tool);
|
||||
|
@ -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
|
||||
@ -26,9 +26,7 @@ package org.graalvm.compiler.nodes.calc;
|
||||
|
||||
import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_1;
|
||||
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.function.Function;
|
||||
import static org.graalvm.compiler.nodes.calc.BinaryArithmeticNode.getArithmeticOpTable;
|
||||
|
||||
import org.graalvm.compiler.core.common.type.ArithmeticOpTable;
|
||||
import org.graalvm.compiler.core.common.type.ArithmeticOpTable.ShiftOp;
|
||||
@ -55,25 +53,21 @@ public abstract class ShiftNode<OP> extends BinaryNode implements ArithmeticOper
|
||||
|
||||
@SuppressWarnings("rawtypes") public static final NodeClass<ShiftNode> TYPE = NodeClass.create(ShiftNode.class);
|
||||
|
||||
protected interface SerializableShiftFunction<T> extends Function<ArithmeticOpTable, ShiftOp<T>>, Serializable {
|
||||
}
|
||||
|
||||
protected final SerializableShiftFunction<OP> getOp;
|
||||
|
||||
/**
|
||||
* Creates a new shift operation.
|
||||
*
|
||||
* @param x the first input value
|
||||
* @param s the second input value
|
||||
*/
|
||||
protected ShiftNode(NodeClass<? extends ShiftNode<OP>> c, SerializableShiftFunction<OP> getOp, ValueNode x, ValueNode s) {
|
||||
super(c, getOp.apply(ArithmeticOpTable.forStamp(x.stamp(NodeView.DEFAULT))).foldStamp(x.stamp(NodeView.DEFAULT), (IntegerStamp) s.stamp(NodeView.DEFAULT)), x, s);
|
||||
protected ShiftNode(NodeClass<? extends ShiftNode<OP>> c, ShiftOp<OP> opForStampComputation, ValueNode x, ValueNode s) {
|
||||
super(c, opForStampComputation.foldStamp(x.stamp(NodeView.DEFAULT), (IntegerStamp) s.stamp(NodeView.DEFAULT)), x, s);
|
||||
assert ((IntegerStamp) s.stamp(NodeView.DEFAULT)).getBits() == 32;
|
||||
this.getOp = getOp;
|
||||
}
|
||||
|
||||
protected abstract ShiftOp<OP> getOp(ArithmeticOpTable table);
|
||||
|
||||
protected final ShiftOp<OP> getOp(ValueNode forValue) {
|
||||
return getOp.apply(ArithmeticOpTable.forStamp(forValue.stamp(NodeView.DEFAULT)));
|
||||
return getOp(getArithmeticOpTable(forValue));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 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,8 +25,8 @@
|
||||
package org.graalvm.compiler.nodes.calc;
|
||||
|
||||
import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_1;
|
||||
import static org.graalvm.compiler.nodes.calc.BinaryArithmeticNode.getArithmeticOpTable;
|
||||
|
||||
import jdk.vm.ci.code.CodeUtil;
|
||||
import org.graalvm.compiler.core.common.type.ArithmeticOpTable;
|
||||
import org.graalvm.compiler.core.common.type.ArithmeticOpTable.IntegerConvertOp;
|
||||
import org.graalvm.compiler.core.common.type.ArithmeticOpTable.IntegerConvertOp.Narrow;
|
||||
@ -42,6 +42,8 @@ import org.graalvm.compiler.nodes.NodeView;
|
||||
import org.graalvm.compiler.nodes.ValueNode;
|
||||
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
|
||||
|
||||
import jdk.vm.ci.code.CodeUtil;
|
||||
|
||||
/**
|
||||
* The {@code SignExtendNode} converts an integer to a wider integer using sign extension.
|
||||
*/
|
||||
@ -56,7 +58,7 @@ public final class SignExtendNode extends IntegerConvertNode<SignExtend, Narrow>
|
||||
}
|
||||
|
||||
public SignExtendNode(ValueNode input, int inputBits, int resultBits) {
|
||||
super(TYPE, ArithmeticOpTable::getSignExtend, ArithmeticOpTable::getNarrow, inputBits, resultBits, input);
|
||||
super(TYPE, getArithmeticOpTable(input).getSignExtend(), inputBits, resultBits, input);
|
||||
}
|
||||
|
||||
public static ValueNode create(ValueNode input, int resultBits, NodeView view) {
|
||||
@ -72,6 +74,16 @@ public final class SignExtendNode extends IntegerConvertNode<SignExtend, Narrow>
|
||||
return canonical(null, input, inputBits, resultBits, view);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IntegerConvertOp<SignExtend> getOp(ArithmeticOpTable table) {
|
||||
return table.getSignExtend();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IntegerConvertOp<Narrow> getReverseOp(ArithmeticOpTable table) {
|
||||
return table.getNarrow();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLossless() {
|
||||
return true;
|
||||
|
@ -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
|
||||
@ -26,8 +26,10 @@ package org.graalvm.compiler.nodes.calc;
|
||||
|
||||
import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_16;
|
||||
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1;
|
||||
import static org.graalvm.compiler.nodes.calc.BinaryArithmeticNode.getArithmeticOpTable;
|
||||
|
||||
import org.graalvm.compiler.core.common.type.ArithmeticOpTable;
|
||||
import org.graalvm.compiler.core.common.type.ArithmeticOpTable.UnaryOp;
|
||||
import org.graalvm.compiler.core.common.type.ArithmeticOpTable.UnaryOp.Sqrt;
|
||||
import org.graalvm.compiler.graph.NodeClass;
|
||||
import org.graalvm.compiler.lir.gen.ArithmeticLIRGeneratorTool;
|
||||
@ -47,7 +49,7 @@ public final class SqrtNode extends UnaryArithmeticNode<Sqrt> implements Arithme
|
||||
public static final NodeClass<SqrtNode> TYPE = NodeClass.create(SqrtNode.class);
|
||||
|
||||
protected SqrtNode(ValueNode x) {
|
||||
super(TYPE, ArithmeticOpTable::getSqrt, x);
|
||||
super(TYPE, getArithmeticOpTable(x).getSqrt(), x);
|
||||
}
|
||||
|
||||
public static ValueNode create(ValueNode x, NodeView view) {
|
||||
@ -58,6 +60,11 @@ public final class SqrtNode extends UnaryArithmeticNode<Sqrt> implements Arithme
|
||||
return new SqrtNode(x);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected UnaryOp<Sqrt> getOp(ArithmeticOpTable table) {
|
||||
return table.getSqrt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generate(NodeLIRBuilderTool nodeValueMap, ArithmeticLIRGeneratorTool gen) {
|
||||
nodeValueMap.setResult(this, gen.emitMathSqrt(nodeValueMap.operand(getValue())));
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 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
|
||||
@ -53,7 +53,7 @@ public class SubNode extends BinaryArithmeticNode<Sub> implements NarrowableArit
|
||||
}
|
||||
|
||||
protected SubNode(NodeClass<? extends SubNode> c, ValueNode x, ValueNode y) {
|
||||
super(c, ArithmeticOpTable::getSub, x, y);
|
||||
super(c, getArithmeticOpTable(x).getSub(), x, y);
|
||||
}
|
||||
|
||||
public static ValueNode create(ValueNode x, ValueNode y, NodeView view) {
|
||||
@ -66,6 +66,11 @@ public class SubNode extends BinaryArithmeticNode<Sub> implements NarrowableArit
|
||||
return canonical(null, op, stamp, x, y, view);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BinaryOp<Sub> getOp(ArithmeticOpTable table) {
|
||||
return table.getSub();
|
||||
}
|
||||
|
||||
private static ValueNode canonical(SubNode subNode, BinaryOp<Sub> op, Stamp stamp, ValueNode forX, ValueNode forY, NodeView view) {
|
||||
SubNode self = subNode;
|
||||
if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 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
|
||||
@ -24,8 +24,7 @@
|
||||
|
||||
package org.graalvm.compiler.nodes.calc;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.function.Function;
|
||||
import static org.graalvm.compiler.nodes.calc.BinaryArithmeticNode.getArithmeticOpTable;
|
||||
|
||||
import org.graalvm.compiler.core.common.type.ArithmeticOpTable;
|
||||
import org.graalvm.compiler.core.common.type.ArithmeticOpTable.UnaryOp;
|
||||
@ -44,18 +43,14 @@ public abstract class UnaryArithmeticNode<OP> extends UnaryNode implements Arith
|
||||
|
||||
@SuppressWarnings("rawtypes") public static final NodeClass<UnaryArithmeticNode> TYPE = NodeClass.create(UnaryArithmeticNode.class);
|
||||
|
||||
protected interface SerializableUnaryFunction<T> extends Function<ArithmeticOpTable, UnaryOp<T>>, Serializable {
|
||||
protected UnaryArithmeticNode(NodeClass<? extends UnaryArithmeticNode<OP>> c, UnaryOp<OP> opForStampComputation, ValueNode value) {
|
||||
super(c, opForStampComputation.foldStamp(value.stamp(NodeView.DEFAULT)), value);
|
||||
}
|
||||
|
||||
protected final SerializableUnaryFunction<OP> getOp;
|
||||
|
||||
protected UnaryArithmeticNode(NodeClass<? extends UnaryArithmeticNode<OP>> c, SerializableUnaryFunction<OP> getOp, ValueNode value) {
|
||||
super(c, getOp.apply(ArithmeticOpTable.forStamp(value.stamp(NodeView.DEFAULT))).foldStamp(value.stamp(NodeView.DEFAULT)), value);
|
||||
this.getOp = getOp;
|
||||
}
|
||||
protected abstract UnaryOp<OP> getOp(ArithmeticOpTable table);
|
||||
|
||||
protected final UnaryOp<OP> getOp(ValueNode forValue) {
|
||||
return getOp.apply(ArithmeticOpTable.forStamp(forValue.stamp(NodeView.DEFAULT)));
|
||||
return getOp(getArithmeticOpTable(forValue));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -24,8 +24,10 @@
|
||||
|
||||
package org.graalvm.compiler.nodes.calc;
|
||||
|
||||
import jdk.vm.ci.code.CodeUtil;
|
||||
import static org.graalvm.compiler.nodes.calc.BinaryArithmeticNode.getArithmeticOpTable;
|
||||
|
||||
import org.graalvm.compiler.core.common.type.ArithmeticOpTable;
|
||||
import org.graalvm.compiler.core.common.type.ArithmeticOpTable.ShiftOp;
|
||||
import org.graalvm.compiler.core.common.type.ArithmeticOpTable.ShiftOp.UShr;
|
||||
import org.graalvm.compiler.core.common.type.IntegerStamp;
|
||||
import org.graalvm.compiler.core.common.type.Stamp;
|
||||
@ -38,6 +40,7 @@ import org.graalvm.compiler.nodes.NodeView;
|
||||
import org.graalvm.compiler.nodes.ValueNode;
|
||||
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
|
||||
|
||||
import jdk.vm.ci.code.CodeUtil;
|
||||
import jdk.vm.ci.meta.JavaKind;
|
||||
|
||||
@NodeInfo(shortName = ">>>")
|
||||
@ -46,7 +49,7 @@ public final class UnsignedRightShiftNode extends ShiftNode<UShr> {
|
||||
public static final NodeClass<UnsignedRightShiftNode> TYPE = NodeClass.create(UnsignedRightShiftNode.class);
|
||||
|
||||
public UnsignedRightShiftNode(ValueNode x, ValueNode y) {
|
||||
super(TYPE, ArithmeticOpTable::getUShr, x, y);
|
||||
super(TYPE, getArithmeticOpTable(x).getUShr(), x, y);
|
||||
}
|
||||
|
||||
public static ValueNode create(ValueNode x, ValueNode y, NodeView view) {
|
||||
@ -60,6 +63,11 @@ public final class UnsignedRightShiftNode extends ShiftNode<UShr> {
|
||||
return canonical(null, op, stamp, x, y, view);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ShiftOp<UShr> getOp(ArithmeticOpTable table) {
|
||||
return table.getUShr();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
|
||||
NodeView view = NodeView.from(tool);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 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,7 +50,7 @@ public final class XorNode extends BinaryArithmeticNode<Xor> implements BinaryCo
|
||||
public static final NodeClass<XorNode> TYPE = NodeClass.create(XorNode.class);
|
||||
|
||||
public XorNode(ValueNode x, ValueNode y) {
|
||||
super(TYPE, ArithmeticOpTable::getXor, x, y);
|
||||
super(TYPE, getArithmeticOpTable(x).getXor(), x, y);
|
||||
assert x.stamp(NodeView.DEFAULT).isCompatible(y.stamp(NodeView.DEFAULT));
|
||||
}
|
||||
|
||||
@ -64,6 +64,11 @@ public final class XorNode extends BinaryArithmeticNode<Xor> implements BinaryCo
|
||||
return canonical(null, op, stamp, x, y, view);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BinaryOp<Xor> getOp(ArithmeticOpTable table) {
|
||||
return table.getXor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
|
||||
ValueNode ret = super.canonical(tool, forX, forY);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 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,6 +25,7 @@
|
||||
package org.graalvm.compiler.nodes.calc;
|
||||
|
||||
import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_1;
|
||||
import static org.graalvm.compiler.nodes.calc.BinaryArithmeticNode.getArithmeticOpTable;
|
||||
|
||||
import org.graalvm.compiler.core.common.calc.CanonicalCondition;
|
||||
import org.graalvm.compiler.core.common.type.ArithmeticOpTable;
|
||||
@ -60,7 +61,7 @@ public final class ZeroExtendNode extends IntegerConvertNode<ZeroExtend, Narrow>
|
||||
}
|
||||
|
||||
public ZeroExtendNode(ValueNode input, int inputBits, int resultBits, boolean inputAlwaysPositive) {
|
||||
super(TYPE, ArithmeticOpTable::getZeroExtend, ArithmeticOpTable::getNarrow, inputBits, resultBits, input);
|
||||
super(TYPE, getArithmeticOpTable(input).getZeroExtend(), inputBits, resultBits, input);
|
||||
this.inputAlwaysPositive = inputAlwaysPositive;
|
||||
}
|
||||
|
||||
@ -81,6 +82,16 @@ public final class ZeroExtendNode extends IntegerConvertNode<ZeroExtend, Narrow>
|
||||
return canonical(null, input, inputBits, resultBits, view, alwaysPositive);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IntegerConvertOp<ZeroExtend> getOp(ArithmeticOpTable table) {
|
||||
return table.getZeroExtend();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IntegerConvertOp<Narrow> getReverseOp(ArithmeticOpTable table) {
|
||||
return table.getNarrow();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLossless() {
|
||||
return true;
|
||||
|
@ -429,11 +429,14 @@ public final class IntegerSwitchNode extends SwitchNode implements LIRLowerable,
|
||||
}
|
||||
|
||||
/*
|
||||
* Collect dead successors. Successors have to be cleaned before adding the new node to the
|
||||
* graph.
|
||||
* Surviving successors have to be cleaned before adding the new node to the graph. Keep the
|
||||
* dead ones attached to the old node for later cleanup.
|
||||
*/
|
||||
List<AbstractBeginNode> deadSuccessors = successors.filter(s -> !newSuccessors.contains(s)).snapshot();
|
||||
successors.clear();
|
||||
for (int i = 0; i < successors.size(); i++) {
|
||||
if (newSuccessors.contains(successors.get(i))) {
|
||||
successors.set(i, null);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Create the new switch node. This is done before removing dead successors as `killCFG`
|
||||
@ -443,14 +446,11 @@ public final class IntegerSwitchNode extends SwitchNode implements LIRLowerable,
|
||||
AbstractBeginNode[] successorsArray = newSuccessors.toArray(new AbstractBeginNode[newSuccessors.size()]);
|
||||
SwitchNode newSwitch = graph().add(new IntegerSwitchNode(newValue, successorsArray, newKeys, newKeyProbabilities, newKeySuccessors));
|
||||
|
||||
/* Remove dead successors. */
|
||||
for (AbstractBeginNode successor : deadSuccessors) {
|
||||
GraphUtil.killCFG(successor);
|
||||
}
|
||||
|
||||
/* Replace ourselves with the new switch */
|
||||
((FixedWithNextNode) predecessor()).setNext(newSwitch);
|
||||
GraphUtil.killWithUnusedFloatingInputs(this);
|
||||
|
||||
// Remove the old switch and the dead successors.
|
||||
GraphUtil.killCFG(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -53,8 +53,7 @@ public interface LoweringProvider {
|
||||
Integer smallestCompareWidth();
|
||||
|
||||
/**
|
||||
* Returns the granularity in terms of bytes that this target platform's bulk zeroing supports.
|
||||
* Returns 0 to indicate that this target platform does not support bulk zeroing instruction.
|
||||
* Indicates whether this target platform supports bulk zeroing of arbitrary size.
|
||||
*/
|
||||
int bulkZeroingStride();
|
||||
boolean supportsBulkZeroing();
|
||||
}
|
||||
|
@ -742,19 +742,22 @@ public class GraphUtil {
|
||||
|
||||
/**
|
||||
* Tries to find an original value of the given node by traversing through proxies and
|
||||
* unambiguous phis. Note that this method will perform an exhaustive search through phis. It is
|
||||
* intended to be used during graph building, when phi nodes aren't yet canonicalized.
|
||||
* unambiguous phis. Note that this method will perform an exhaustive search through phis.
|
||||
*
|
||||
* @param value The node whose original value should be determined.
|
||||
* @return The original value (which might be the input value itself).
|
||||
* @param value the node whose original value should be determined
|
||||
* @param abortOnLoopPhi specifies if the traversal through phis should stop and return
|
||||
* {@code value} if it hits a {@linkplain PhiNode#isLoopPhi loop phi}. This argument
|
||||
* must be {@code true} if used during graph building as loop phi nodes may not yet
|
||||
* have all their inputs computed.
|
||||
* @return the original value (which might be {@code value} itself)
|
||||
*/
|
||||
public static ValueNode originalValue(ValueNode value) {
|
||||
ValueNode result = originalValueSimple(value);
|
||||
public static ValueNode originalValue(ValueNode value, boolean abortOnLoopPhi) {
|
||||
ValueNode result = originalValueSimple(value, abortOnLoopPhi);
|
||||
assert result != null;
|
||||
return result;
|
||||
}
|
||||
|
||||
private static ValueNode originalValueSimple(ValueNode value) {
|
||||
private static ValueNode originalValueSimple(ValueNode value, boolean abortOnLoopPhi) {
|
||||
/* The very simple case: look through proxies. */
|
||||
ValueNode cur = originalValueForProxy(value);
|
||||
|
||||
@ -765,6 +768,10 @@ public class GraphUtil {
|
||||
*/
|
||||
PhiNode phi = (PhiNode) cur;
|
||||
|
||||
if (abortOnLoopPhi && phi.isLoopPhi()) {
|
||||
return value;
|
||||
}
|
||||
|
||||
ValueNode phiSingleValue = null;
|
||||
int count = phi.valueCount();
|
||||
for (int i = 0; i < count; ++i) {
|
||||
@ -783,7 +790,7 @@ public class GraphUtil {
|
||||
* of the inputs is another phi function. We need to do a complicated
|
||||
* exhaustive check.
|
||||
*/
|
||||
return originalValueForComplicatedPhi(phi, new NodeBitMap(value.graph()));
|
||||
return originalValueForComplicatedPhi(value, phi, new NodeBitMap(value.graph()), abortOnLoopPhi);
|
||||
} else {
|
||||
/*
|
||||
* We have two different input values for the phi function, but none of them
|
||||
@ -819,8 +826,12 @@ public class GraphUtil {
|
||||
/**
|
||||
* Handling for complicated nestings of phi functions. We need to reduce phi functions
|
||||
* recursively, and need a temporary map of visited nodes to avoid endless recursion of cycles.
|
||||
*
|
||||
* @param value the node whose original value is being determined
|
||||
* @param abortOnLoopPhi specifies if the traversal through phis should stop and return
|
||||
* {@code value} if it hits a {@linkplain PhiNode#isLoopPhi loop phi}
|
||||
*/
|
||||
private static ValueNode originalValueForComplicatedPhi(PhiNode phi, NodeBitMap visited) {
|
||||
private static ValueNode originalValueForComplicatedPhi(ValueNode value, PhiNode phi, NodeBitMap visited, boolean abortOnLoopPhi) {
|
||||
if (visited.isMarked(phi)) {
|
||||
/*
|
||||
* Found a phi function that was already seen. Either a cycle, or just a second phi
|
||||
@ -836,7 +847,16 @@ public class GraphUtil {
|
||||
ValueNode phiCurValue = originalValueForProxy(phi.valueAt(i));
|
||||
if (phiCurValue instanceof PhiNode) {
|
||||
/* Recursively process a phi function input. */
|
||||
phiCurValue = originalValueForComplicatedPhi((PhiNode) phiCurValue, visited);
|
||||
PhiNode curPhi = (PhiNode) phiCurValue;
|
||||
if (abortOnLoopPhi && curPhi.isLoopPhi()) {
|
||||
return value;
|
||||
}
|
||||
phiCurValue = originalValueForComplicatedPhi(value, curPhi, visited, abortOnLoopPhi);
|
||||
if (phiCurValue == value) {
|
||||
// Hit a loop phi
|
||||
assert abortOnLoopPhi;
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
if (phiCurValue == null) {
|
||||
|
@ -47,6 +47,7 @@ import org.graalvm.compiler.nodes.memory.address.AddressNode;
|
||||
import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode;
|
||||
import org.graalvm.compiler.replacements.TargetGraphBuilderPlugins;
|
||||
import org.graalvm.compiler.replacements.nodes.BinaryMathIntrinsicNode;
|
||||
import org.graalvm.compiler.replacements.nodes.FusedMultiplyAddNode;
|
||||
import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode;
|
||||
import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation;
|
||||
import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
|
||||
@ -61,16 +62,11 @@ public class AArch64GraphBuilderPlugins implements TargetGraphBuilderPlugins {
|
||||
@Override
|
||||
public void register(Plugins plugins, BytecodeProvider replacementsBytecodeProvider, Architecture arch, boolean explicitUnsafeNullChecks, boolean registerMathPlugins,
|
||||
boolean emitJDK9StringSubstitutions, boolean useFMAIntrinsics) {
|
||||
register(plugins, replacementsBytecodeProvider, explicitUnsafeNullChecks, registerMathPlugins, emitJDK9StringSubstitutions);
|
||||
register(plugins, replacementsBytecodeProvider, explicitUnsafeNullChecks, registerMathPlugins, emitJDK9StringSubstitutions, useFMAIntrinsics);
|
||||
}
|
||||
|
||||
public static void register(Plugins plugins, BytecodeProvider bytecodeProvider, boolean explicitUnsafeNullChecks,
|
||||
boolean registerMathPlugins) {
|
||||
register(plugins, bytecodeProvider, explicitUnsafeNullChecks, registerMathPlugins, true);
|
||||
}
|
||||
|
||||
public static void register(Plugins plugins, BytecodeProvider bytecodeProvider, boolean explicitUnsafeNullChecks,
|
||||
boolean registerMathPlugins, boolean emitJDK9StringSubstitutions) {
|
||||
boolean registerMathPlugins, boolean emitJDK9StringSubstitutions, boolean useFMAIntrinsics) {
|
||||
InvocationPlugins invocationPlugins = plugins.getInvocationPlugins();
|
||||
invocationPlugins.defer(new Runnable() {
|
||||
@Override
|
||||
@ -78,7 +74,7 @@ public class AArch64GraphBuilderPlugins implements TargetGraphBuilderPlugins {
|
||||
registerIntegerLongPlugins(invocationPlugins, JavaKind.Int, bytecodeProvider);
|
||||
registerIntegerLongPlugins(invocationPlugins, JavaKind.Long, bytecodeProvider);
|
||||
if (registerMathPlugins) {
|
||||
registerMathPlugins(invocationPlugins);
|
||||
registerMathPlugins(invocationPlugins, useFMAIntrinsics);
|
||||
}
|
||||
if (emitJDK9StringSubstitutions) {
|
||||
registerStringLatin1Plugins(invocationPlugins, bytecodeProvider);
|
||||
@ -130,7 +126,7 @@ public class AArch64GraphBuilderPlugins implements TargetGraphBuilderPlugins {
|
||||
});
|
||||
}
|
||||
|
||||
private static void registerMathPlugins(InvocationPlugins plugins) {
|
||||
private static void registerMathPlugins(InvocationPlugins plugins, boolean useFMAIntrinsics) {
|
||||
Registration r = new Registration(plugins, Math.class);
|
||||
registerUnaryMath(r, "sin", SIN);
|
||||
registerUnaryMath(r, "cos", COS);
|
||||
@ -148,6 +144,36 @@ public class AArch64GraphBuilderPlugins implements TargetGraphBuilderPlugins {
|
||||
registerRound(r, "rint", RoundingMode.NEAREST);
|
||||
registerRound(r, "ceil", RoundingMode.UP);
|
||||
registerRound(r, "floor", RoundingMode.DOWN);
|
||||
if (useFMAIntrinsics && JavaVersionUtil.JAVA_SPEC > 8) {
|
||||
registerFMA(r);
|
||||
}
|
||||
}
|
||||
|
||||
private static void registerFMA(Registration r) {
|
||||
r.register3("fma", Double.TYPE, Double.TYPE, Double.TYPE, new InvocationPlugin() {
|
||||
@Override
|
||||
public boolean apply(GraphBuilderContext b,
|
||||
ResolvedJavaMethod targetMethod,
|
||||
Receiver receiver,
|
||||
ValueNode na,
|
||||
ValueNode nb,
|
||||
ValueNode nc) {
|
||||
b.push(JavaKind.Double, b.append(new FusedMultiplyAddNode(na, nb, nc)));
|
||||
return true;
|
||||
}
|
||||
});
|
||||
r.register3("fma", Float.TYPE, Float.TYPE, Float.TYPE, new InvocationPlugin() {
|
||||
@Override
|
||||
public boolean apply(GraphBuilderContext b,
|
||||
ResolvedJavaMethod targetMethod,
|
||||
Receiver receiver,
|
||||
ValueNode na,
|
||||
ValueNode nb,
|
||||
ValueNode nc) {
|
||||
b.push(JavaKind.Float, b.append(new FusedMultiplyAddNode(na, nb, nc)));
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void registerUnaryMath(Registration r, String name, UnaryOperation operation) {
|
||||
|
@ -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
|
||||
@ -26,10 +26,12 @@ package org.graalvm.compiler.replacements.amd64;
|
||||
|
||||
import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_8;
|
||||
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1;
|
||||
import static org.graalvm.compiler.nodes.calc.BinaryArithmeticNode.getArithmeticOpTable;
|
||||
|
||||
import jdk.vm.ci.meta.JavaConstant;
|
||||
import org.graalvm.compiler.core.common.calc.FloatConvert;
|
||||
import org.graalvm.compiler.core.common.type.ArithmeticOpTable;
|
||||
import org.graalvm.compiler.core.common.type.ArithmeticOpTable.FloatConvertOp;
|
||||
import org.graalvm.compiler.core.common.type.ArithmeticOpTable.UnaryOp;
|
||||
import org.graalvm.compiler.core.common.type.IntegerStamp;
|
||||
import org.graalvm.compiler.core.common.type.Stamp;
|
||||
import org.graalvm.compiler.core.common.type.StampFactory;
|
||||
@ -43,6 +45,8 @@ import org.graalvm.compiler.nodes.calc.UnaryArithmeticNode;
|
||||
import org.graalvm.compiler.nodes.spi.ArithmeticLIRLowerable;
|
||||
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
|
||||
|
||||
import jdk.vm.ci.meta.JavaConstant;
|
||||
|
||||
/**
|
||||
* This node has the semantics of the AMD64 floating point conversions. It is used in the lowering
|
||||
* of the {@link FloatConvertNode} which, on AMD64 needs a {@link AMD64FloatConvertNode} plus some
|
||||
@ -58,11 +62,16 @@ public final class AMD64FloatConvertNode extends UnaryArithmeticNode<FloatConver
|
||||
protected final FloatConvert op;
|
||||
|
||||
public AMD64FloatConvertNode(FloatConvert op, ValueNode value) {
|
||||
super(TYPE, table -> table.getFloatConvert(op), value);
|
||||
super(TYPE, getArithmeticOpTable(value).getFloatConvert(op), value);
|
||||
this.op = op;
|
||||
this.stamp = this.stamp.meet(createInexactCaseStamp());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected UnaryOp<FloatConvertOp> getOp(ArithmeticOpTable table) {
|
||||
return table.getFloatConvert(op);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) {
|
||||
// nothing to do
|
||||
|
@ -87,13 +87,6 @@ import java.util.Formatter;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
import org.graalvm.compiler.test.ModuleSupport;
|
||||
import org.graalvm.compiler.test.SubprocessUtil;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Assume;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
|
||||
import org.graalvm.compiler.api.test.Graal;
|
||||
import org.graalvm.compiler.bytecode.Bytecode;
|
||||
@ -111,6 +104,12 @@ import org.graalvm.compiler.replacements.classfile.ClassfileBytecode;
|
||||
import org.graalvm.compiler.replacements.classfile.ClassfileBytecodeProvider;
|
||||
import org.graalvm.compiler.runtime.RuntimeProvider;
|
||||
import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
|
||||
import org.graalvm.compiler.test.ModuleSupport;
|
||||
import org.graalvm.compiler.test.SubprocessUtil;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Assume;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import jdk.vm.ci.meta.ConstantPool;
|
||||
import jdk.vm.ci.meta.JavaField;
|
||||
@ -209,6 +208,17 @@ public class ClassfileBytecodeProviderTest extends GraalCompilerTest {
|
||||
}
|
||||
try {
|
||||
checkClass(metaAccess, getSnippetReflection(), className);
|
||||
} catch (UnsupportedClassVersionError e) {
|
||||
// graal-test.jar can contain classes compiled for different
|
||||
// Java versions
|
||||
} catch (NoClassDefFoundError e) {
|
||||
if (!e.getMessage().contains("Could not initialize class")) {
|
||||
throw e;
|
||||
} else {
|
||||
// A second or later attempt to initialize a class
|
||||
// results in this confusing error where the
|
||||
// original cause of initialization failure is lost
|
||||
}
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
|
@ -835,7 +835,7 @@ public class StandardGraphBuilderPlugins {
|
||||
@Override
|
||||
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
|
||||
ValueNode object = receiver.get();
|
||||
ValueNode folded = GetClassNode.tryFold(b.getMetaAccess(), b.getConstantReflection(), NodeView.DEFAULT, GraphUtil.originalValue(object));
|
||||
ValueNode folded = GetClassNode.tryFold(b.getMetaAccess(), b.getConstantReflection(), NodeView.DEFAULT, GraphUtil.originalValue(object, true));
|
||||
if (folded != null) {
|
||||
b.addPush(JavaKind.Object, folded);
|
||||
} else {
|
||||
|
@ -48,19 +48,21 @@ public class ZeroMemoryNode extends FixedAccessNode implements LIRLowerable {
|
||||
public static final NodeClass<ZeroMemoryNode> TYPE = NodeClass.create(ZeroMemoryNode.class);
|
||||
|
||||
@Input ValueNode length;
|
||||
private final boolean isAligned;
|
||||
|
||||
public ZeroMemoryNode(ValueNode address, ValueNode length, LocationIdentity locationIdentity) {
|
||||
this(OffsetAddressNode.create(address), length, locationIdentity, BarrierType.NONE);
|
||||
public ZeroMemoryNode(ValueNode address, ValueNode length, boolean isAligned, LocationIdentity locationIdentity) {
|
||||
this(OffsetAddressNode.create(address), length, isAligned, locationIdentity, BarrierType.NONE);
|
||||
}
|
||||
|
||||
public ZeroMemoryNode(AddressNode address, ValueNode length, LocationIdentity locationIdentity, BarrierType type) {
|
||||
public ZeroMemoryNode(AddressNode address, ValueNode length, boolean isAligned, LocationIdentity locationIdentity, BarrierType type) {
|
||||
super(TYPE, address, locationIdentity, StampFactory.forVoid(), type);
|
||||
this.length = length;
|
||||
this.isAligned = isAligned;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generate(NodeLIRBuilderTool gen) {
|
||||
gen.getLIRGeneratorTool().emitZeroMemory(gen.operand(getAddress()), gen.operand(length));
|
||||
gen.getLIRGeneratorTool().emitZeroMemory(gen.operand(getAddress()), gen.operand(length), isAligned);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -69,5 +71,5 @@ public class ZeroMemoryNode extends FixedAccessNode implements LIRLowerable {
|
||||
}
|
||||
|
||||
@NodeIntrinsic
|
||||
public static native void zero(Word address, long length, @ConstantNodeParameter LocationIdentity locationIdentity);
|
||||
public static native void zero(Word address, long length, @ConstantNodeParameter boolean isAligned, @ConstantNodeParameter LocationIdentity locationIdentity);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 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
|
||||
@ -28,6 +28,7 @@ import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_2;
|
||||
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_2;
|
||||
|
||||
import org.graalvm.compiler.core.common.type.ArithmeticOpTable;
|
||||
import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp;
|
||||
import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp.UMulHigh;
|
||||
import org.graalvm.compiler.graph.NodeClass;
|
||||
import org.graalvm.compiler.graph.spi.Canonicalizable;
|
||||
@ -49,7 +50,12 @@ public final class UnsignedMulHighNode extends BinaryArithmeticNode<UMulHigh> im
|
||||
public static final NodeClass<UnsignedMulHighNode> TYPE = NodeClass.create(UnsignedMulHighNode.class);
|
||||
|
||||
public UnsignedMulHighNode(ValueNode x, ValueNode y) {
|
||||
super(TYPE, ArithmeticOpTable::getUMulHigh, x, y);
|
||||
super(TYPE, getArithmeticOpTable(x).getUMulHigh(), x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BinaryOp<UMulHigh> getOp(ArithmeticOpTable table) {
|
||||
return table.getUMulHigh();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 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
|
||||
@ -30,10 +30,17 @@ final class DefaultGraphTypes implements GraphTypes {
|
||||
private DefaultGraphTypes() {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Class<?> enumClass(Object enumValue) {
|
||||
if (enumValue instanceof Enum<?>) {
|
||||
return enumValue.getClass();
|
||||
// check that the enum class is not actually an anonymous subclass:
|
||||
Class<? extends Enum<?>> enumClass = (Class<? extends Enum<?>>) enumValue.getClass();
|
||||
Enum<?>[] constants = enumClass.getEnumConstants();
|
||||
if (constants == null && enumClass.isAnonymousClass()) {
|
||||
enumClass = (Class<? extends Enum<?>>) enumClass.getSuperclass();
|
||||
}
|
||||
return enumClass;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user