8231973: Update Graal

Reviewed-by: kvn
This commit is contained in:
Dean Long 2019-10-09 21:53:48 -07:00
parent 2918f86d2b
commit 183e2e119d
78 changed files with 1333 additions and 523 deletions

View File

@ -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

View File

@ -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());

View File

@ -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;
}

View File

@ -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();
}
}

View File

@ -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++) {

View File

@ -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;
}

View File

@ -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));

View File

@ -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));
}
}

View File

@ -35,7 +35,7 @@ public interface AArch64LoweringProviderMixin extends LoweringProvider {
}
@Override
default int bulkZeroingStride() {
return 8;
default boolean supportsBulkZeroing() {
return true;
}
}

View File

@ -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));

View File

@ -35,7 +35,7 @@ public interface AMD64LoweringProviderMixin extends LoweringProvider {
}
@Override
default int bulkZeroingStride() {
return 1;
default boolean supportsBulkZeroing() {
return true;
}
}

View File

@ -35,7 +35,7 @@ public interface SparcLoweringProviderMixin extends LoweringProvider {
}
@Override
default int bulkZeroingStride() {
return 0;
default boolean supportsBulkZeroing() {
return false;
}
}

View File

@ -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);
}

View File

@ -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"));
}
}
}

View File

@ -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")) {

View File

@ -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";
}
}
}
}

View File

@ -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;

View File

@ -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();

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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,

View File

@ -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()]);
}

View File

@ -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");

View File

@ -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);
}

View File

@ -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) {

View File

@ -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.

View File

@ -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
}
}
}

View File

@ -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.
}

View File

@ -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 {

View File

@ -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);

View File

@ -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();
}

View File

@ -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));

View File

@ -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);

View File

@ -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

View File

@ -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();
}

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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");
}
}

View File

@ -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) {

View File

@ -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() {
}
}

View File

@ -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>() {

View File

@ -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();

View File

@ -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);

View File

@ -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();

View File

@ -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);

View File

@ -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

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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());

View File

@ -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));

View File

@ -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);

View File

@ -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);
}

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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())));

View File

@ -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)) {

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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();
}

View File

@ -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) {

View File

@ -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) {

View File

@ -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

View File

@ -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);
}

View File

@ -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 {

View File

@ -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);
}

View File

@ -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

View File

@ -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;
}