8247922: Update Graal

Reviewed-by: kvn
This commit is contained in:
Dean Long 2020-07-02 13:03:32 -07:00
parent ec25b42804
commit 8b7c959164
132 changed files with 2717 additions and 975 deletions

View File

@ -477,6 +477,7 @@ jdk.internal.vm.compiler_EXCLUDES += \
org.graalvm.compiler.options.test \
org.graalvm.compiler.phases.common.test \
org.graalvm.compiler.processor \
org.graalvm.compiler.replacements.jdk10.test \
org.graalvm.compiler.replacements.jdk12.test \
org.graalvm.compiler.replacements.jdk9.test \
org.graalvm.compiler.replacements.processor \

View File

@ -105,6 +105,7 @@ ifeq ($(INCLUDE_GRAAL), true)
$(SRC_DIR)/org.graalvm.compiler.nodes.test/src \
$(SRC_DIR)/org.graalvm.compiler.options.test/src \
$(SRC_DIR)/org.graalvm.compiler.phases.common.test/src \
$(SRC_DIR)/org.graalvm.compiler.replacements.jdk10.test/src \
$(SRC_DIR)/org.graalvm.compiler.replacements.jdk12.test/src \
$(SRC_DIR)/org.graalvm.compiler.replacements.jdk9.test/src \
$(SRC_DIR)/org.graalvm.compiler.replacements.test/src \

View File

@ -38,7 +38,7 @@ module jdk.internal.vm.compiler {
uses org.graalvm.compiler.hotspot.HotSpotBackendFactory;
uses org.graalvm.compiler.hotspot.HotSpotCodeCacheListener;
uses org.graalvm.compiler.hotspot.HotSpotGraalManagementRegistration;
uses org.graalvm.compiler.nodes.graphbuilderconf.NodeIntrinsicPluginFactory;
uses org.graalvm.compiler.nodes.graphbuilderconf.GeneratedPluginFactory;
uses org.graalvm.compiler.phases.common.jmx.HotSpotMBeanOperationProvider;
uses org.graalvm.compiler.serviceprovider.JMXService;

View File

@ -208,7 +208,7 @@ class TestProtectedAssembler extends AArch64Assembler {
}
@Override
protected void sbfm(int size, Register dst, Register src, int r, int s) {
public void sbfm(int size, Register dst, Register src, int r, int s) {
super.sbfm(size, dst, src, r, s);
}

View File

@ -1852,7 +1852,7 @@ public abstract class AArch64Assembler extends Assembler {
* @param r must be in the range 0 to size - 1
* @param s must be in the range 0 to size - 1
*/
protected void sbfm(int size, Register dst, Register src, int r, int s) {
public void sbfm(int size, Register dst, Register src, int r, int s) {
bitfieldInstruction(SBFM, dst, src, r, s, generalFromSize(size));
}

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, Arm Limited and affiliates. All rights reserved.
* Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2020, Arm Limited and affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -36,12 +36,16 @@ public class AArch64BitFieldTest extends AArch64MatchRuleTest {
private static final Predicate<LIRInstruction> predicate = op -> (op instanceof AArch64BitFieldOp);
private void testAndCheckLIR(String method, String negativeMethod, Object input) {
test(method, input);
checkLIR(method, predicate, 1);
testAndCheckLIR(method, input);
test(negativeMethod, input);
checkLIR(negativeMethod, predicate, 0);
}
private void testAndCheckLIR(String method, Object input) {
test(method, input);
checkLIR(method, predicate, 1);
}
/**
* unsigned bit field extract int.
*/
@ -133,4 +137,174 @@ public class AArch64BitFieldTest extends AArch64MatchRuleTest {
public void testInsertLong() {
testAndCheckLIR("insertLong", "invalidInsertLong", 0xdeadbeefdeadbeefL);
}
// Tests for unsigned bitfield move, with integration of zero extend (I2L) operation.
//
// UBFIZ with I2L.
public static long unsignedInsertExtend(int input) {
return ((long) (input & 0xffff)) << 8;
}
@Test
public void testUnsignedInsertExtend() {
testAndCheckLIR("unsignedInsertExtend", 0x234);
}
// I2L with UBFIZ.
public static long unsignedExtendInsert(int input) {
return (input & 0xfff) << 5;
}
@Test
public void testUnsignedExtendInsert() {
testAndCheckLIR("unsignedExtendInsert", 0x4334);
}
// I2L with UBFX.
public static long unsignedExtendExtract(int input) {
return (input >>> 6) & 0xffffff;
}
@Test
public void testUnsignedExtendExtract() {
testAndCheckLIR("unsignedExtendExtract", 0x325ab);
}
// Signed bitfield insert with extend, generated by (LeftShift (SignExtend value) a) match
// rule.
// SBFIZ with B2L.
public long signedB2LInsert(long input) {
byte b = (byte) input;
return ((long) b) << 2;
}
@Test
public void testSignedB2LInsert() {
testAndCheckLIR("signedB2LInsert", 0xab3213efL);
}
// SBFIZ with S2L.
public long signedS2LInsert(long input) {
short s = (short) input;
return ((long) s) << -5;
}
@Test
public void testSignedS2LInsert() {
testAndCheckLIR("signedS2LInsert", 0x328032bL);
}
// SBFIZ with I2L.
public static long signedI2LInsert(int input) {
return ((long) input) << 1;
}
@Test
public void testSignedI2LInsert() {
testAndCheckLIR("signedI2LInsert", 31);
}
// SBFIZ with B2I.
public int signedB2IInsert(int input) {
byte b = (byte) input;
return b << 31;
}
@Test
public void testSignedB2IInsert() {
testAndCheckLIR("signedB2IInsert", 0x23);
}
// SBFIZ with S2I.
public int signedS2IInsert(int input) {
short s = (short) input;
return s << 2;
}
@Test
public void testSignedS2IInsert() {
testAndCheckLIR("signedS2IInsert", 0x92);
}
// Tests for bitfield move generated by ([Unsigned]RightShift (LeftShift value a) b) match
// rules.
// SBFX for int.
public static int signedExtractInt(int input) {
return (input << 8) >> 15;
}
@Test
public void testSignedExtractInt() {
testAndCheckLIR("signedExtractInt", 0x123);
}
// SBFX for long.
public static long signedExtractLong(long input) {
return (input << 8) >> 15;
}
@Test
public void testSignedExtractLong() {
testAndCheckLIR("signedExtractLong", 0x125L);
}
// SBFIZ for int.
public static int signedInsertInt(int input) {
return (input << 15) >> 8;
}
@Test
public void testSignedInsertInt() {
testAndCheckLIR("signedInsertInt", 0x1253);
}
// SBFIZ for long.
public static long signedInsertLong(long input) {
return (input << 15) >> 8;
}
@Test
public void testSignedInsertLong() {
testAndCheckLIR("signedInsertLong", 0xabcddbc325L);
}
// UBFX for int.
public static int unsignedExtractInt(int input) {
return (input << 8) >>> 31;
}
@Test
public void testUnsignedExtractInt() {
testAndCheckLIR("unsignedExtractInt", 0x125);
}
// UBFX for long.
public static long unsignedExtractLong(long input) {
return (input << 8) >>> 12;
}
@Test
public void testUnsignedExtractLong() {
testAndCheckLIR("unsignedExtractLong", 0x32222e125L);
}
// UBFIZ for int.
public static int unsignedInsertInt(int input) {
return (input << 15) >>> 8;
}
@Test
public void testUnsignedInsertInt() {
testAndCheckLIR("unsignedInsertInt", 125);
}
// UBFIZ for long.
public static long unsignedInsertLong(long input) {
return (input << 63) >>> 1;
}
@Test
public void testUnsignedInsertLong() {
testAndCheckLIR("unsignedInsertLong", 0x2339fb125L);
}
}

View File

@ -371,7 +371,7 @@ public class AArch64ArithmeticLIRGenerator extends ArithmeticLIRGenerator implem
}
}
private void emitBinaryConst(Variable result, AArch64ArithmeticOp op, AllocatableValue a, JavaConstant b) {
public void emitBinaryConst(Variable result, AArch64ArithmeticOp op, AllocatableValue a, JavaConstant b) {
AllocatableValue x = moveSp(a);
getLIRGen().append(new AArch64ArithmeticOp.BinaryConstOp(op, result, x, b));
}

View File

@ -42,6 +42,7 @@ import org.graalvm.compiler.lir.LabelRef;
import org.graalvm.compiler.lir.Variable;
import org.graalvm.compiler.lir.aarch64.AArch64ArithmeticOp;
import org.graalvm.compiler.lir.aarch64.AArch64BitFieldOp;
import org.graalvm.compiler.lir.aarch64.AArch64BitFieldOp.BitFieldOpCode;
import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow;
import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
import org.graalvm.compiler.nodes.ConstantNode;
@ -73,6 +74,7 @@ import org.graalvm.compiler.nodes.memory.MemoryAccess;
import jdk.vm.ci.aarch64.AArch64Kind;
import jdk.vm.ci.code.CodeUtil;
import jdk.vm.ci.meta.AllocatableValue;
import jdk.vm.ci.meta.JavaConstant;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.Value;
@ -96,8 +98,8 @@ public class AArch64NodeMatchRules extends NodeMatchRules {
binaryOpMap.put(UnsignedRightShiftNode.class, AArch64ArithmeticOp.LSHR);
bitFieldOpMap = EconomicMap.create(Equivalence.IDENTITY, 2);
bitFieldOpMap.put(UnsignedRightShiftNode.class, AArch64BitFieldOp.BitFieldOpCode.UBFX);
bitFieldOpMap.put(LeftShiftNode.class, AArch64BitFieldOp.BitFieldOpCode.UBFIZ);
bitFieldOpMap.put(UnsignedRightShiftNode.class, BitFieldOpCode.UBFX);
bitFieldOpMap.put(LeftShiftNode.class, BitFieldOpCode.UBFIZ);
logicalNotOpMap = EconomicMap.create(Equivalence.IDENTITY, 3);
logicalNotOpMap.put(AndNode.class, AArch64ArithmeticOp.BIC);
@ -161,19 +163,6 @@ public class AArch64NodeMatchRules extends NodeMatchRules {
return getLIRGeneratorTool().moveSp(value);
}
private ComplexMatchResult emitBitField(AArch64BitFieldOp.BitFieldOpCode op, ValueNode value, int lsb, int width) {
assert op != null;
assert value.getStackKind().isNumericInteger();
return builder -> {
Value a = operand(value);
Variable result = gen.newVariable(LIRKind.combine(a));
AllocatableValue src = moveSp(gen.asAllocatable(a));
gen.append(new AArch64BitFieldOp(op, result, src, lsb, width));
return result;
};
}
private ComplexMatchResult emitBinaryShift(AArch64ArithmeticOp op, ValueNode value, BinaryNode shift) {
AArch64MacroAssembler.ShiftType shiftType = shiftTypeMap.get(shift.getClass());
assert shiftType != null;
@ -205,6 +194,51 @@ public class AArch64NodeMatchRules extends NodeMatchRules {
};
}
private ComplexMatchResult emitBitField(JavaKind kind, AArch64BitFieldOp.BitFieldOpCode op, ValueNode value, int lsb, int width) {
assert op != null;
assert value.getStackKind().isNumericInteger();
return builder -> {
Value a = operand(value);
LIRKind resultKind = LIRKind.fromJavaKind(gen.target().arch, kind);
Variable result = gen.newVariable(resultKind);
AllocatableValue src = moveSp(gen.asAllocatable(a));
gen.append(new AArch64BitFieldOp(op, result, src, lsb, width));
return result;
};
}
private ComplexMatchResult emitUnsignedBitField(JavaKind kind, BinaryNode shift, ValueNode value, ConstantNode scale, ConstantNode mask) {
assert kind.isNumericInteger();
BitFieldOpCode op = bitFieldOpMap.get(shift.getClass());
assert op != null;
JavaKind srcKind = shift.getStackKind();
// The Java(R) Language Specification CHAPTER 15.19 Shift Operators says:
// "If the promoted type of the left-hand operand is int(long), then only the five(six)
// lowest-order bits of the right-hand operand are used as the shift distance."
int distance = scale.asJavaConstant().asInt();
int lsb = distance & (srcKind == JavaKind.Int ? 0x1F : 0x3F);
long maskValue = mask.asJavaConstant().asLong();
// Constraint 1: Mask plus one should be a power-of-2 integer.
if (!CodeUtil.isPowerOf2(maskValue + 1)) {
return null;
}
int width = CodeUtil.log2(maskValue + 1);
int srcBits = srcKind.getBitCount();
// Constraint 2: Bit field width is less than 31(63) for int(long) as any bit field move
// operations can be done by a single shift instruction if the width is 31(63).
if (width >= srcBits - 1) {
return null;
}
// Constraint 3: Sum of bit field width and the shift distance is less or equal to 32(64)
// for int(long) as the specification of AArch64 bit field instructions.
if (width + distance > srcBits) {
return null;
}
return emitBitField(kind, op, value, lsb, width);
}
private static boolean isNarrowingLongToInt(NarrowNode narrow) {
return narrow.getInputBits() == Long.SIZE && narrow.getResultBits() == Integer.SIZE;
}
@ -325,38 +359,68 @@ public class AArch64NodeMatchRules extends NodeMatchRules {
return null;
}
@MatchRule("(And (UnsignedRightShift=shift a Constant=b) Constant=c)")
@MatchRule("(LeftShift=shift (And a Constant=c) Constant=b)")
public ComplexMatchResult unsignedBitField(BinaryNode shift, ValueNode a, ConstantNode b, ConstantNode c) {
JavaKind srcKind = a.getStackKind();
@MatchRule("(And (UnsignedRightShift=shift value Constant=a) Constant=b)")
@MatchRule("(LeftShift=shift (And value Constant=b) Constant=a)")
public ComplexMatchResult unsignedBitField(BinaryNode shift, ValueNode value, ConstantNode a, ConstantNode b) {
JavaKind kind = shift.getStackKind();
return emitUnsignedBitField(kind, shift, value, a, b);
}
@MatchRule("(LeftShift=shift (ZeroExtend=extend (And value Constant=b)) Constant=a)")
@MatchRule("(ZeroExtend=extend (And (UnsignedRightShift=shift value Constant=a) Constant=b))")
@MatchRule("(ZeroExtend=extend (LeftShift=shift (And value Constant=b) Constant=a))")
public ComplexMatchResult unsignedExtBitField(ZeroExtendNode extend, BinaryNode shift, ValueNode value, ConstantNode a, ConstantNode b) {
JavaKind kind = extend.getStackKind();
return emitUnsignedBitField(kind, shift, value, a, b);
}
@MatchRule("(LeftShift=shift (SignExtend value) Constant)")
public ComplexMatchResult signedBitField(LeftShiftNode shift) {
JavaKind kind = shift.getStackKind();
assert kind.isNumericInteger();
SignExtendNode extend = (SignExtendNode) shift.getX();
int srcBits = extend.getInputBits();
int resultBits = extend.getResultBits();
assert kind.getBitCount() == resultBits;
int lsb = shift.getY().asJavaConstant().asInt() & (resultBits - 1);
// Get the min value of the srcBits and (resultBits - lsb) as the bitfield width.
int width = Math.min(srcBits, resultBits - lsb);
assert width >= 1 && width <= resultBits - lsb;
ValueNode value = extend.getValue();
return emitBitField(kind, BitFieldOpCode.SBFIZ, value, lsb, width);
}
@MatchRule("(RightShift=rshift (LeftShift=lshift value Constant) Constant)")
@MatchRule("(UnsignedRightShift=rshift (LeftShift=lshift value Constant) Constant)")
public ComplexMatchResult bitFieldMove(BinaryNode rshift, LeftShiftNode lshift) {
JavaKind srcKind = rshift.getStackKind();
assert srcKind.isNumericInteger();
AArch64BitFieldOp.BitFieldOpCode op = bitFieldOpMap.get(shift.getClass());
assert op != null;
int distance = b.asJavaConstant().asInt();
long mask = c.asJavaConstant().asLong();
// The Java(R) Language Specification CHAPTER 15.19 Shift Operators says:
// "If the promoted type of the left-hand operand is int(long), then only the five(six)
// lowest-order bits of the right-hand operand are used as the shift distance."
distance = distance & (srcKind == JavaKind.Int ? 0x1f : 0x3f);
// Constraint 1: Mask plus one should be a power-of-2 integer.
if (!CodeUtil.isPowerOf2(mask + 1)) {
return null;
}
int width = CodeUtil.log2(mask + 1);
int srcBits = srcKind.getBitCount();
// Constraint 2: Bit field width is less than 31(63) for int(long) as any bit field move
// operations can be done by a single shift instruction if the width is 31(63).
if (width >= srcBits - 1) {
int lshiftNum = lshift.getY().asJavaConstant().asInt() & (srcBits - 1);
int rshiftNum = rshift.getY().asJavaConstant().asInt() & (srcBits - 1);
int lsb = Math.abs(lshiftNum - rshiftNum);
assert lsb >= 0 && lsb <= (srcBits - 1);
// Get the width of the bitField. It should be in the range 1 to 32(64)-<lsb>.
int width = srcBits - Math.max(lshiftNum, rshiftNum);
if (width > (srcBits - lsb) || width < 1) {
return null;
}
// Constraint 3: Sum of bit field width and the shift distance is less or equal to 32(64)
// for int(long) as the specification of AArch64 bit field instructions.
if (width + distance > srcBits) {
return null;
// Use bitfield insert (SBFIZ/UBFIZ) if left shift number is larger than right shift number,
// otherwise use bitfield extract (SBFX/UBFX).
boolean bitFieldInsert = lshiftNum > rshiftNum;
BitFieldOpCode op;
if (rshift instanceof RightShiftNode) {
op = bitFieldInsert ? BitFieldOpCode.SBFIZ : BitFieldOpCode.SBFX;
} else {
assert rshift instanceof UnsignedRightShiftNode;
op = bitFieldInsert ? BitFieldOpCode.UBFIZ : BitFieldOpCode.UBFX;
}
return emitBitField(op, a, distance, width);
return emitBitField(srcKind, op, lshift.getX(), lsb, width);
}
@MatchRule("(Or=op (LeftShift=x src Constant=shiftAmt1) (UnsignedRightShift src Constant=shiftAmt2))")
@ -375,9 +439,11 @@ public class AArch64NodeMatchRules extends NodeMatchRules {
}
if ((0 == shift1 + shift2) || (src.getStackKind().getBitCount() == shift1 + shift2)) {
return builder -> {
Value a = operand(src);
Value b = x instanceof LeftShiftNode ? operand(shiftAmt2) : operand(shiftAmt1);
return getArithmeticLIRGenerator().emitBinary(LIRKind.combine(a, b), AArch64ArithmeticOp.ROR, false, a, b);
AllocatableValue a = gen.asAllocatable(operand(src));
JavaConstant b = x instanceof LeftShiftNode ? shiftAmt2.asJavaConstant() : shiftAmt1.asJavaConstant();
Variable result = gen.newVariable(LIRKind.combine(a));
getArithmeticLIRGenerator().emitBinaryConst(result, AArch64ArithmeticOp.ROR, a, b);
return result;
};
}
return null;

View File

@ -692,21 +692,26 @@ public class AMD64ArithmeticLIRGenerator extends ArithmeticLIRGenerator implemen
}
private Variable emitShift(AMD64Shift op, OperandSize size, Value a, Value b) {
if (isJavaConstant(b)) {
return emitShiftConst(op, size, a, asJavaConstant(b));
}
Variable result = getLIRGen().newVariable(LIRKind.combine(a, b).changeType(a.getPlatformKind()));
AllocatableValue input = asAllocatable(a);
if (isJavaConstant(b)) {
JavaConstant c = asJavaConstant(b);
if (c.asLong() == 1) {
getLIRGen().emitMove(RCX_I, b);
getLIRGen().append(new AMD64ShiftOp(op.mcOp, size, result, input, RCX_I));
return result;
}
public Variable emitShiftConst(AMD64Shift op, OperandSize size, Value a, JavaConstant b) {
Variable result = getLIRGen().newVariable(LIRKind.combine(a).changeType(a.getPlatformKind()));
AllocatableValue input = asAllocatable(a);
if (b.asLong() == 1) {
getLIRGen().append(new AMD64Unary.MOp(op.m1Op, size, result, input));
} else {
/*
* c needs to be masked here, because shifts with immediate expect a byte.
*/
getLIRGen().append(new AMD64Binary.ConstOp(op.miOp, size, result, input, (byte) c.asLong()));
}
} else {
getLIRGen().emitMove(RCX_I, b);
getLIRGen().append(new AMD64ShiftOp(op.mcOp, size, result, input, RCX_I));
getLIRGen().append(new AMD64Binary.ConstOp(op.miOp, size, result, input, (byte) b.asLong()));
}
return result;
}

View File

@ -33,6 +33,7 @@ import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmeti
import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RMOp.MOVSX;
import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RMOp.MOVSXB;
import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RMOp.MOVSXD;
import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64Shift.ROL;
import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRVMOp.VADDSD;
import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRVMOp.VADDSS;
import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRVMOp.VMULSD;
@ -449,8 +450,15 @@ public class AMD64NodeMatchRules extends NodeMatchRules {
@MatchRule("(Or (LeftShift=lshift value Constant) (UnsignedRightShift=rshift value Constant))")
public ComplexMatchResult rotateLeftConstant(LeftShiftNode lshift, UnsignedRightShiftNode rshift) {
if ((lshift.getShiftAmountMask() & (lshift.getY().asJavaConstant().asInt() + rshift.getY().asJavaConstant().asInt())) == 0) {
return builder -> getArithmeticLIRGenerator().emitRol(operand(lshift.getX()), operand(lshift.getY()));
JavaConstant lshiftConst = lshift.getY().asJavaConstant();
JavaConstant rshiftConst = rshift.getY().asJavaConstant();
if ((lshift.getShiftAmountMask() & (lshiftConst.asInt() + rshiftConst.asInt())) == 0) {
return builder -> {
Value a = operand(lshift.getX());
OperandSize size = OperandSize.get(a.getPlatformKind());
assert size == OperandSize.DWORD || size == OperandSize.QWORD;
return getArithmeticLIRGenerator().emitShiftConst(ROL, size, a, lshiftConst);
};
}
return null;
}

View File

@ -343,11 +343,16 @@ public class MatchProcessor extends AbstractProcessor {
final boolean commutative;
/**
* Can multiple users of this node subsume it. Constants can be swallowed into a match even
* if there are multiple users.
* Can multiple users of this node subsume it.
*/
final boolean shareable;
/**
* Can this node be swallowed into a match. Constants can be consumed by a match even if it
* has multiple users.
*/
final boolean consumable;
/**
* Can this node be subsumed into a match even if there are side effecting nodes between
* this node and the match.
@ -356,7 +361,8 @@ public class MatchProcessor extends AbstractProcessor {
final Set<Element> originatingElements = new HashSet<>();
TypeDescriptor(TypeMirror mirror, String shortName, String nodeClass, String nodePackage, List<String> inputs, boolean commutative, boolean shareable, boolean ignoresSideEffects) {
TypeDescriptor(TypeMirror mirror, String shortName, String nodeClass, String nodePackage, List<String> inputs,
boolean commutative, boolean shareable, boolean consumable, boolean ignoresSideEffects) {
this.mirror = mirror;
this.shortName = shortName;
this.nodeClass = nodeClass;
@ -364,6 +370,7 @@ public class MatchProcessor extends AbstractProcessor {
this.inputs = inputs;
this.commutative = commutative;
this.shareable = shareable;
this.consumable = consumable;
this.ignoresSideEffects = ignoresSideEffects;
assert !commutative || inputs.size() == 2;
}
@ -376,9 +383,9 @@ public class MatchProcessor extends AbstractProcessor {
private TypeDescriptor valueType;
private void declareType(TypeMirror mirror, String shortName, String nodeClass, String nodePackage, List<String> inputs, boolean commutative, boolean shareable, boolean ignoresSideEffects,
Element element) {
TypeDescriptor descriptor = new TypeDescriptor(mirror, shortName, nodeClass, nodePackage, inputs, commutative, shareable, ignoresSideEffects);
private void declareType(TypeMirror mirror, String shortName, String nodeClass, String nodePackage, List<String> inputs,
boolean commutative, boolean shareable, boolean consumable, boolean ignoresSideEffects, Element element) {
TypeDescriptor descriptor = new TypeDescriptor(mirror, shortName, nodeClass, nodePackage, inputs, commutative, shareable, consumable, ignoresSideEffects);
descriptor.originatingElements.add(element);
knownTypes.put(shortName, descriptor);
}
@ -461,7 +468,7 @@ public class MatchProcessor extends AbstractProcessor {
private String formatPrefix() {
if (nodeType == valueType) {
return String.format("new MatchPattern(%s, false, false", name != null ? ("\"" + name + "\"") : "null");
return String.format("new MatchPattern(%s, false, false, false", name != null ? ("\"" + name + "\"") : "null");
} else {
return String.format("new MatchPattern(%s.class, %s", nodeType.nodeClass, name != null ? ("\"" + name + "\"") : "null");
}
@ -470,13 +477,13 @@ public class MatchProcessor extends AbstractProcessor {
private String formatSuffix() {
if (nodeType != null) {
if (inputs.length != nodeType.inputs.size()) {
return ", true, " + nodeType.ignoresSideEffects + ")";
return ", true, " + nodeType.consumable + ", " + nodeType.ignoresSideEffects + ")";
} else {
if (nodeType.inputs.size() > 0) {
return ", " + nodeType.nodeClass + "_positions, " + !nodeType.shareable + ", " + nodeType.ignoresSideEffects + ")";
return ", " + nodeType.nodeClass + "_positions, " + !nodeType.shareable + ", " + nodeType.consumable + ", " + nodeType.ignoresSideEffects + ")";
}
if (nodeType.shareable) {
return ", false, " + nodeType.ignoresSideEffects + ")";
return ", false, " + nodeType.consumable + ", " + nodeType.ignoresSideEffects + ")";
}
}
}
@ -732,7 +739,7 @@ public class MatchProcessor extends AbstractProcessor {
// Define a TypeDescriptor for the generic node but don't enter it into the nodeTypes
// table since it shouldn't be mentioned in match rules.
TypeMirror valueTypeMirror = getTypeElement(VALUE_NODE_CLASS_NAME).asType();
valueType = new TypeDescriptor(valueTypeMirror, "Value", "ValueNode", "org.graalvm.compiler.nodes", Collections.emptyList(), false, false, false);
valueType = new TypeDescriptor(valueTypeMirror, "Value", "ValueNode", "org.graalvm.compiler.nodes", Collections.emptyList(), false, false, false, false);
Map<TypeElement, MatchRuleDescriptor> map = new HashMap<>();
@ -842,8 +849,9 @@ public class MatchProcessor extends AbstractProcessor {
boolean commutative = getAnnotationValue(matchable, "commutative", Boolean.class);
boolean shareable = getAnnotationValue(matchable, "shareable", Boolean.class);
boolean consumable = getAnnotationValue(matchable, "consumable", Boolean.class);
boolean ignoresSideEffects = getAnnotationValue(matchable, "ignoresSideEffects", Boolean.class);
declareType(nodeClassMirror, shortName, nodeClass, nodePackage, inputs, commutative, shareable, ignoresSideEffects, element);
declareType(nodeClassMirror, shortName, nodeClass, nodePackage, inputs, commutative, shareable, consumable, ignoresSideEffects, element);
}
private void processMatchRules(Map<TypeElement, MatchRuleDescriptor> map, Element element, List<AnnotationMirror> matchRules) {

View File

@ -538,7 +538,7 @@ public class CheckGraalInvariants extends GraalCompilerTest {
}
private static boolean isInNativeImage(String className) {
return className.startsWith("org.graalvm.nativeimage");
return className.startsWith("jdk.internal.vm.compiler.nativeimage");
}
private static boolean isGSON(String className) {

View File

@ -4,9 +4,7 @@
*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
* 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
@ -22,6 +20,8 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.graalvm.compiler.core.test;
import java.io.IOException;
@ -59,6 +59,8 @@ public class DeepUnrollingTest extends SubprocessTest {
return v;
}
private static final int ACCEPTABLE_FACTOR = 50;
public void loopTest() {
// warmup
time("reference");
@ -66,7 +68,9 @@ public class DeepUnrollingTest extends SubprocessTest {
long reference = time("reference");
long loops = time("loops");
// observed ratio is ~20-30x. Pathological case before fix was ~300x
assertTrue("Compilation of the loop nest is too slow", loops < reference * 45);
if (loops > reference * ACCEPTABLE_FACTOR) {
fail("Compilation of the loop nest is too slow. loops: %dms > %d * reference: %dms", loops, ACCEPTABLE_FACTOR, reference);
}
}
public long time(String methodName) {

View File

@ -105,7 +105,7 @@ public class UnschedulableGraphTest extends GraalCompilerTest {
try (AutoCloseable c = new TTY.Filter();
DebugContext debug = getDebugContext(method);
DebugCloseable s = debug.disableIntercept()) {
test("snippet01", 0, 1, 2);
test(debug.getOptions(), "snippet01", 0, 1, 2);
Assert.fail("Compilation should not reach this point, must throw an exception before");
} catch (Throwable t) {
if (t.getMessage().contains("liveIn set of first block must be empty")) {

View File

@ -188,17 +188,28 @@ public class GraalCompiler {
}
}
if (crashLabel != null) {
String crashMessage = "Forced crash after compiling " + crashLabel;
notifyCrash(crashMessage);
if (permanentBailout) {
throw new PermanentBailoutException("Forced crash after compiling " + crashLabel);
throw new PermanentBailoutException(crashMessage);
}
if (bailout) {
throw new RetryableBailoutException("Forced crash after compiling " + crashLabel);
throw new RetryableBailoutException(crashMessage);
}
throw new RuntimeException("Forced crash after compiling " + crashLabel);
throw new RuntimeException(crashMessage);
}
}
}
/**
* Substituted by {@code com.oracle.svm.graal.hotspot.libgraal.
* Target_org_graalvm_compiler_core_GraalCompiler} to optionally test routing fatal error
* handling from libgraal to HotSpot.
*/
@SuppressWarnings("unused")
private static void notifyCrash(String crashMessage) {
}
/**
* Builds the graph, optimizes it.
*/

View File

@ -30,6 +30,7 @@ import static jdk.vm.ci.code.ValueUtil.isRegister;
import static org.graalvm.compiler.core.common.GraalOptions.MatchExpressions;
import static org.graalvm.compiler.core.common.SpeculativeExecutionAttacksMitigations.AllTargets;
import static org.graalvm.compiler.core.common.SpeculativeExecutionAttacksMitigations.Options.MitigateSpeculativeExecutionAttacks;
import static org.graalvm.compiler.core.match.ComplexMatchValue.INTERIOR_MATCH;
import static org.graalvm.compiler.debug.DebugOptions.LogVerbose;
import static org.graalvm.compiler.lir.LIR.verifyBlock;
@ -137,6 +138,7 @@ public abstract class NodeLIRBuilder implements NodeLIRBuilderTool, LIRGeneratio
private final NodeMatchRules nodeMatchRules;
private EconomicMap<Class<? extends Node>, List<MatchStatement>> matchRules;
private EconomicMap<Node, Integer> sharedMatchCounts;
public NodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool gen, NodeMatchRules nodeMatchRules) {
this.gen = (LIRGenerator) gen;
@ -146,6 +148,7 @@ public abstract class NodeLIRBuilder implements NodeLIRBuilderTool, LIRGeneratio
OptionValues options = graph.getOptions();
if (MatchExpressions.getValue(options)) {
matchRules = MatchRuleRegistry.lookup(nodeMatchRules.getClass(), options, graph.getDebug());
sharedMatchCounts = EconomicMap.create();
}
traceLIRGeneratorLevel = TTY.isSuppressed() ? 0 : Options.TraceLIRGeneratorLevel.getValue(options);
@ -219,13 +222,30 @@ public abstract class NodeLIRBuilder implements NodeLIRBuilderTool, LIRGeneratio
* ValueNodes.
*/
public void setMatchResult(Node x, Value operand) {
assert operand.equals(ComplexMatchValue.INTERIOR_MATCH) || operand instanceof ComplexMatchValue;
assert operand.equals(INTERIOR_MATCH) || operand instanceof ComplexMatchValue;
assert operand instanceof ComplexMatchValue || MatchPattern.isSingleValueUser(x) : "interior matches must be single user";
assert nodeOperands != null && nodeOperands.get(x) == null : "operand cannot be set twice";
assert !(x instanceof VirtualObjectNode);
nodeOperands.set(x, operand);
}
/**
* Track how many users have consumed a sharedable match and disable emission of the value if
* all users have consumed it.
*/
public void incrementSharedMatchCount(Node node) {
assert nodeOperands != null && nodeOperands.get(node) == null : "operand cannot be set twice";
Integer matchValue = sharedMatchCounts.get(node);
if (matchValue == null) {
matchValue = 0;
}
matchValue = matchValue + 1;
sharedMatchCounts.put(node, matchValue);
if (node.getUsageCount() == matchValue) {
nodeOperands.set(node, INTERIOR_MATCH);
}
}
public LabelRef getLIRBlock(FixedNode b) {
assert gen.getResult().getLIR().getControlFlowGraph() instanceof ControlFlowGraph;
Block result = ((ControlFlowGraph) gen.getResult().getLIR().getControlFlowGraph()).blockFor(b);
@ -384,7 +404,7 @@ public abstract class NodeLIRBuilder implements NodeLIRBuilderTool, LIRGeneratio
throw new GraalGraphError(e).addContext(valueNode);
}
}
} else if (ComplexMatchValue.INTERIOR_MATCH.equals(operand)) {
} else if (INTERIOR_MATCH.equals(operand)) {
// Doesn't need to be evaluated
debug.log("interior match for %s", valueNode);
} else if (operand instanceof ComplexMatchValue) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -68,10 +68,12 @@ public class MatchContext {
static final class ConsumedNode {
final Node node;
final boolean ignoresSideEffects;
final boolean singleUser;
ConsumedNode(Node node, boolean ignoresSideEffects) {
ConsumedNode(Node node, boolean ignoresSideEffects, boolean singleUser) {
this.node = node;
this.ignoresSideEffects = ignoresSideEffects;
this.singleUser = singleUser;
}
}
@ -85,11 +87,11 @@ public class MatchContext {
this.nodes = null;
}
public void add(Node node, boolean ignoresSideEffects) {
public void add(Node node, boolean ignoresSideEffects, boolean singlerUser) {
if (nodes == null) {
nodes = new ArrayList<>(2);
}
nodes.add(new ConsumedNode(node, ignoresSideEffects));
nodes.add(new ConsumedNode(node, ignoresSideEffects, singlerUser));
}
public boolean contains(Node node) {
@ -373,10 +375,7 @@ public class MatchContext {
if (cn.node == root || cn.node == emitNode) {
continue;
}
// All the interior nodes should be skipped during the normal doRoot calls in
// NodeLIRBuilder so mark them as interior matches. The root of the match will get a
// closure which will be evaluated to produce the final LIR.
builder.setMatchResult(cn.node, ComplexMatchValue.INTERIOR_MATCH);
setResult(cn);
}
builder.setMatchResult(emitNode, value);
if (root != emitNode) {
@ -387,23 +386,34 @@ public class MatchContext {
}
}
private void setResult(ConsumedNode consumedNode) {
Node node = consumedNode.node;
if (consumedNode.singleUser) {
// All the interior nodes should be skipped during the normal doRoot calls in
// NodeLIRBuilder so mark them as interior matches. The root of the match will get a
// closure which will be evaluated to produce the final LIR.
builder.setMatchResult(node, ComplexMatchValue.INTERIOR_MATCH);
return;
}
builder.incrementSharedMatchCount(node);
}
/**
* Mark a node as consumed by the match. Consumed nodes will never be evaluated.
*
* @return Result.OK if the node can be safely consumed.
*/
public Result consume(Node node, boolean ignoresSideEffects, boolean atRoot) {
public Result consume(Node node, boolean ignoresSideEffects, boolean atRoot, boolean singleUser) {
if (atRoot) {
consumed.add(node, ignoresSideEffects);
consumed.add(node, ignoresSideEffects, singleUser);
return Result.OK;
}
assert MatchPattern.isSingleValueUser(node) : "should have already been checked";
if (builder.hasOperand(node)) {
return Result.alreadyUsed(node, rule.getPattern());
}
consumed.add(node, ignoresSideEffects);
consumed.add(node, ignoresSideEffects, singleUser);
return Result.OK;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -158,6 +158,8 @@ public class MatchPattern {
*/
private final boolean singleUser;
private final boolean consumable;
/**
* Can this node be subsumed into a match even if there are side effecting nodes between this
* node and the match.
@ -166,41 +168,47 @@ public class MatchPattern {
private static final MatchPattern[] EMPTY_PATTERNS = new MatchPattern[0];
public MatchPattern(String name, boolean singleUser, boolean ignoresSideEffects) {
this(null, name, singleUser, ignoresSideEffects);
public MatchPattern(String name, boolean singleUser, boolean consumable, boolean ignoresSideEffects) {
this(null, name, singleUser, consumable, ignoresSideEffects);
}
public MatchPattern(Class<? extends Node> nodeClass, String name, boolean singleUser, boolean ignoresSideEffects) {
public MatchPattern(Class<? extends Node> nodeClass, String name, boolean singleUser, boolean consumable, boolean ignoresSideEffects) {
this.nodeClass = nodeClass;
this.name = name;
this.singleUser = singleUser;
this.consumable = consumable;
this.ignoresSideEffects = ignoresSideEffects;
this.patterns = EMPTY_PATTERNS;
this.inputs = null;
assert !ignoresSideEffects || FloatingNode.class.isAssignableFrom(nodeClass);
}
private MatchPattern(Class<? extends Node> nodeClass, String name, boolean singleUser, boolean ignoresSideEffects, MatchPattern[] patterns, Position[] inputs) {
private MatchPattern(Class<? extends Node> nodeClass, String name, boolean singleUser, boolean consumable,
boolean ignoresSideEffects, MatchPattern[] patterns, Position[] inputs) {
assert inputs == null || inputs.length == patterns.length;
this.nodeClass = nodeClass;
this.name = name;
this.singleUser = singleUser;
this.consumable = consumable;
this.ignoresSideEffects = ignoresSideEffects;
this.patterns = patterns;
this.inputs = inputs;
assert !ignoresSideEffects || FloatingNode.class.isAssignableFrom(nodeClass);
}
public MatchPattern(Class<? extends Node> nodeClass, String name, MatchPattern first, Position[] inputs, boolean singleUser, boolean ignoresSideEffects) {
this(nodeClass, name, singleUser, ignoresSideEffects, new MatchPattern[]{first}, inputs);
public MatchPattern(Class<? extends Node> nodeClass, String name, MatchPattern first, Position[] inputs,
boolean singleUser, boolean consumable, boolean ignoresSideEffects) {
this(nodeClass, name, singleUser, consumable, ignoresSideEffects, new MatchPattern[]{first}, inputs);
}
public MatchPattern(Class<? extends Node> nodeClass, String name, MatchPattern first, MatchPattern second, Position[] inputs, boolean singleUser, boolean ignoresSideEffects) {
this(nodeClass, name, singleUser, ignoresSideEffects, new MatchPattern[]{first, second}, inputs);
public MatchPattern(Class<? extends Node> nodeClass, String name, MatchPattern first, MatchPattern second,
Position[] inputs, boolean singleUser, boolean consumable, boolean ignoresSideEffects) {
this(nodeClass, name, singleUser, consumable, ignoresSideEffects, new MatchPattern[]{first, second}, inputs);
}
public MatchPattern(Class<? extends Node> nodeClass, String name, MatchPattern first, MatchPattern second, MatchPattern third, Position[] inputs, boolean singleUser, boolean ignoresSideEffects) {
this(nodeClass, name, singleUser, ignoresSideEffects, new MatchPattern[]{first, second, third}, inputs);
public MatchPattern(Class<? extends Node> nodeClass, String name, MatchPattern first, MatchPattern second, MatchPattern third,
Position[] inputs, boolean singleUser, boolean consumable, boolean ignoresSideEffects) {
this(nodeClass, name, singleUser, consumable, ignoresSideEffects, new MatchPattern[]{first, second, third}, inputs);
}
Class<? extends Node> nodeClass() {
@ -234,8 +242,9 @@ public class MatchPattern {
if (result != Result.OK) {
return result;
}
if (singleUser) {
result = context.consume(node, ignoresSideEffects, atRoot);
if (consumable) {
result = context.consume(node, ignoresSideEffects, atRoot, singleUser);
if (result != Result.OK) {
return result;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -66,4 +66,9 @@ public @interface MatchableNode {
boolean shareable() default false;
boolean ignoresSideEffects() default false;
/**
* Can a node be consumed by a matched rule regardless of whether it is shareable.
*/
boolean consumable() default true;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -55,6 +55,10 @@ public class GraalError extends Error {
throw new GraalError(cause);
}
public static RuntimeException shouldNotReachHere(Throwable cause, String msg) {
throw new GraalError(cause, "should not reach here: %s", msg);
}
/**
* Checks a given condition and throws a {@link GraalError} if it is false. Guarantees are
* stronger than assertions in that they are always checked. Error messages for guarantee

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -81,7 +81,7 @@ final class IgvDumpChannel implements WritableByteChannel {
WritableByteChannel channel() throws IOException {
if (closed) {
throw new IOException();
throw new IOException("already closed");
}
if (sharedChannel == null) {
PrintGraphTarget target = DebugOptions.PrintGraph.getValue(options);

View File

@ -154,14 +154,18 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface {
/**
* Annotates a method that can be replaced by a compiler intrinsic. A (resolved) call to the
* annotated method will be processed by a generated {@code InvocationPlugin} that calls either
* a factory method or a constructor corresponding with the annotated method.
* a factory method or a constructor corresponding with the annotated method. By default the
* intrinsics are implemented by invoking the constructor but a factory method may be used
* instead. To use a factory method the class implementing the intrinsic must be annotated with
* {@link NodeIntrinsicFactory}. To ease error checking of NodeIntrinsics all intrinsics are
* expected to be implemented in the same way, so it's not possible to mix constructor and
* factory intrinsification in the same class.
* <p>
* A factory method corresponding to an annotated method is a static method named
* {@code intrinsify} defined in the class denoted by {@link #value()}. In order, its signature
* is as follows:
* <ol>
* <li>A {@code GraphBuilderContext} parameter.</li>
* <li>A {@code ResolvedJavaMethod} parameter.</li>
* <li>A sequence of zero or more {@linkplain InjectedNodeParameter injected} parameters.</li>
* <li>Remaining parameters that match the declared parameters of the annotated method.</li>
* </ol>
@ -199,6 +203,15 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface {
boolean hasSideEffect() default false;
}
/**
* Marker annotation indicating that the class uses factory methods instead of constructors for
* intrinsification.
*/
@java.lang.annotation.Retention(RetentionPolicy.RUNTIME)
@java.lang.annotation.Target(ElementType.TYPE)
public @interface NodeIntrinsicFactory {
}
/**
* Marker for a node that can be replaced by another node via global value numbering. A
* {@linkplain NodeClass#isLeafNode() leaf} node can be replaced by another node of the same

View File

@ -30,10 +30,8 @@ import static org.graalvm.compiler.graph.Edges.translateInto;
import static org.graalvm.compiler.graph.Graph.isModificationCountsEnabled;
import static org.graalvm.compiler.graph.InputEdges.translateInto;
import static org.graalvm.compiler.graph.Node.WithAllEdges;
import static org.graalvm.compiler.serviceprovider.GraalUnsafeAccess.getUnsafe;
import java.lang.annotation.Annotation;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
@ -54,7 +52,6 @@ import org.graalvm.compiler.debug.CounterKey;
import org.graalvm.compiler.debug.DebugCloseable;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.debug.TTY;
import org.graalvm.compiler.debug.TimerKey;
import org.graalvm.compiler.graph.Edges.Type;
import org.graalvm.compiler.graph.Graph.DuplicationReplacement;
@ -71,6 +68,7 @@ import org.graalvm.compiler.nodeinfo.NodeCycles;
import org.graalvm.compiler.nodeinfo.NodeInfo;
import org.graalvm.compiler.nodeinfo.NodeSize;
import org.graalvm.compiler.nodeinfo.Verbosity;
import org.graalvm.compiler.serviceprovider.GraalUnsafeAccess;
import sun.misc.Unsafe;
@ -84,7 +82,7 @@ import sun.misc.Unsafe;
*/
public final class NodeClass<T> extends FieldIntrospection<T> {
private static final Unsafe UNSAFE = getUnsafe();
private static final Unsafe UNSAFE = GraalUnsafeAccess.getUnsafe();
// Timers for creation of a NodeClass instance
private static final TimerKey Init_FieldScanning = DebugContext.timer("NodeClass.Init.FieldScanning");
private static final TimerKey Init_FieldScanningInner = DebugContext.timer("NodeClass.Init.FieldScanning.Inner");
@ -132,40 +130,12 @@ public final class NodeClass<T> extends FieldIntrospection<T> {
}
public static <T> NodeClass<T> get(Class<T> clazz) {
int numTries = 0;
while (true) {
@SuppressWarnings("removal")
boolean shouldBeInitializedBefore = UNSAFE.shouldBeInitialized(clazz);
NodeClass<T> result = getUnchecked(clazz);
if (result != null || clazz == NODE_CLASS) {
return result;
}
/*
* GR-9537: We observed a transient problem with TYPE fields being null. Retry a couple
* of times and print something to the log so that we can gather more diagnostic
* information without failing gates.
*/
numTries++;
@SuppressWarnings("removal")
boolean shouldBeInitializedAfter = UNSAFE.shouldBeInitialized(clazz);
String msg = "GR-9537 Reflective field access of TYPE field returned null. This is probably a bug in HotSpot class initialization. " +
" clazz: " + clazz.getTypeName() + ", numTries: " + numTries +
", shouldBeInitializedBefore: " + shouldBeInitializedBefore + ", shouldBeInitializedAfter: " + shouldBeInitializedAfter;
if (numTries <= 100) {
TTY.println(msg);
try {
MethodHandles.lookup().ensureInitialized(clazz);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
} else {
throw GraalError.shouldNotReachHere(msg);
if (result == null && clazz != NODE_CLASS) {
throw GraalError.shouldNotReachHere("TYPE field not initialized for class " + clazz.getTypeName());
}
return result;
}
}
private static final Class<?> NODE_CLASS = Node.class;
private static final Class<?> INPUT_LIST_CLASS = NodeInputList.class;

View File

@ -395,6 +395,11 @@ public class AArch64HotSpotBackend extends HotSpotHostBackend implements LIRGene
ForeignCallLinkage linkage = foreignCalls.lookupForeignCall(DEOPT_BLOB_UNPACK);
masm.adr(lr, 0); // Warning: the argument is an offset from the instruction!
AArch64Call.directJmp(crb, masm, linkage);
if (config.supportsMethodHandleDeoptimizationEntry() && crb.needsMHDeoptHandler()) {
crb.recordMark(HotSpotMarkId.DEOPT_MH_HANDLER_ENTRY);
masm.adr(lr, 0);
AArch64Call.directJmp(crb, masm, linkage);
}
} else {
// No need to emit the stubs for entries back into the method since
// it has no calls that can cause such "return" entries

View File

@ -66,7 +66,6 @@ import org.graalvm.compiler.phases.Phase;
import org.graalvm.compiler.phases.common.AddressLoweringByUsePhase;
import org.graalvm.compiler.phases.schedule.SchedulePhase;
import org.graalvm.compiler.phases.tiers.CompilerConfiguration;
import org.graalvm.compiler.phases.util.Providers;
import org.graalvm.compiler.replacements.aarch64.AArch64GraphBuilderPlugins;
import org.graalvm.compiler.serviceprovider.ServiceProvider;
import org.graalvm.compiler.word.WordTypes;
@ -151,7 +150,7 @@ public class AArch64HotSpotBackendFactory extends HotSpotBackendFactory {
lowerer = createLowerer(graalRuntime, metaAccess, foreignCalls, registers, constantReflection, platformConfigurationProvider, metaAccessExtensionProvider, target);
}
Providers p = new Providers(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, null, stampProvider, platformConfigurationProvider,
HotSpotProviders p = new HotSpotProviders(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, null, stampProvider, platformConfigurationProvider,
metaAccessExtensionProvider);
try (InitTimer rt = timer("create SnippetReflection provider")) {
@ -172,7 +171,7 @@ public class AArch64HotSpotBackendFactory extends HotSpotBackendFactory {
suites = createSuites(config, graalRuntime, compilerConfiguration, plugins, replacements);
}
providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, suites, registers,
snippetReflection, wordTypes, plugins, platformConfigurationProvider, metaAccessExtensionProvider);
snippetReflection, wordTypes, plugins, platformConfigurationProvider, metaAccessExtensionProvider, config);
replacements.setProviders(providers);
replacements.maybeInitializeEncoder(options);
}

View File

@ -36,6 +36,7 @@ import org.graalvm.compiler.lir.aarch64.AArch64Call.DirectCallOp;
import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind;
import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.meta.Value;
@ -69,6 +70,9 @@ final class AArch64HotSpotDirectStaticCallOp extends DirectCallOp {
// correct inline cache value here.
crb.recordMark(invokeKind == InvokeKind.Static ? HotSpotMarkId.INVOKESTATIC : HotSpotMarkId.INVOKESPECIAL);
masm.movNativeAddress(inlineCacheRegister, config.nonOopBits);
if (config.supportsMethodHandleDeoptimizationEntry() && config.isMethodHandleCall((HotSpotResolvedJavaMethod) callTarget) && invokeKind != InvokeKind.Static) {
crb.setNeedsMHDeoptHandler();
}
super.emitCode(crb, masm);
}
}

View File

@ -36,6 +36,7 @@ import org.graalvm.compiler.lir.aarch64.AArch64Call.DirectCallOp;
import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind;
import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.meta.Value;
@ -69,6 +70,9 @@ final class AArch64HotSpotDirectVirtualCallOp extends DirectCallOp {
// correct inline cache value here.
crb.recordMark(invokeKind == InvokeKind.Virtual ? HotSpotMarkId.INVOKEVIRTUAL : HotSpotMarkId.INVOKEINTERFACE);
masm.movNativeAddress(inlineCacheRegister, config.nonOopBits);
if (config.supportsMethodHandleDeoptimizationEntry() && config.isMethodHandleCall((HotSpotResolvedJavaMethod) callTarget)) {
crb.setNeedsMHDeoptHandler();
}
super.emitCode(crb, masm);
}
}

View File

@ -235,7 +235,7 @@ public class StubAVXTest extends LIRTest {
@Test
public void test() {
HotSpotProviders providers = (HotSpotProviders) getProviders();
HotSpotForeignCallsProviderImpl foreignCalls = (HotSpotForeignCallsProviderImpl) providers.getForeignCalls();
HotSpotForeignCallsProviderImpl foreignCalls = providers.getForeignCalls();
HotSpotForeignCallLinkage linkage = foreignCalls.registerStubCall(TEST_STUB, HotSpotForeignCallDescriptor.Transition.LEAF_NO_VZERO,
HotSpotForeignCallDescriptor.Reexecutability.REEXECUTABLE,
COMPUTES_REGISTERS_KILLED);

View File

@ -331,6 +331,10 @@ public class AMD64HotSpotBackend extends HotSpotHostBackend implements LIRGenera
AMD64Call.directCall(crb, asm, foreignCalls.lookupForeignCall(EXCEPTION_HANDLER), null, false, null);
crb.recordMark(HotSpotMarkId.DEOPT_HANDLER_ENTRY);
AMD64Call.directCall(crb, asm, foreignCalls.lookupForeignCall(DEOPT_BLOB_UNPACK), null, false, null);
if (config.supportsMethodHandleDeoptimizationEntry() && crb.needsMHDeoptHandler()) {
crb.recordMark(HotSpotMarkId.DEOPT_MH_HANDLER_ENTRY);
AMD64Call.directCall(crb, asm, foreignCalls.lookupForeignCall(DEOPT_BLOB_UNPACK), null, false, null);
}
} else {
// No need to emit the stubs for entries back into the method since
// it has no calls that can cause such "return" entries

View File

@ -58,7 +58,6 @@ import org.graalvm.compiler.nodes.spi.Replacements;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.phases.common.AddressLoweringPhase;
import org.graalvm.compiler.phases.tiers.CompilerConfiguration;
import org.graalvm.compiler.phases.util.Providers;
import org.graalvm.compiler.replacements.amd64.AMD64GraphBuilderPlugins;
import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
import org.graalvm.compiler.serviceprovider.ServiceProvider;
@ -143,7 +142,7 @@ public class AMD64HotSpotBackendFactory extends HotSpotBackendFactory {
lowerer = createLowerer(graalRuntime, metaAccess, foreignCalls, registers, constantReflection, platformConfigurationProvider, metaAccessExtensionProvider, target);
}
Providers p = new Providers(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, null, stampProvider, platformConfigurationProvider,
HotSpotProviders p = new HotSpotProviders(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, null, stampProvider, platformConfigurationProvider,
metaAccessExtensionProvider);
try (InitTimer rt = timer("create SnippetReflection provider")) {
@ -164,7 +163,7 @@ public class AMD64HotSpotBackendFactory extends HotSpotBackendFactory {
suites = createSuites(config, graalRuntime, compilerConfiguration, plugins, registers, replacements, options);
}
providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, suites, registers,
snippetReflection, wordTypes, plugins, platformConfigurationProvider, metaAccessExtensionProvider);
snippetReflection, wordTypes, plugins, platformConfigurationProvider, metaAccessExtensionProvider, config);
replacements.setProviders(providers);
replacements.maybeInitializeEncoder(options);
}

View File

@ -25,6 +25,7 @@
package org.graalvm.compiler.hotspot.amd64;
import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
import org.graalvm.compiler.hotspot.HotSpotMarkId;
import org.graalvm.compiler.lir.LIRFrameState;
import org.graalvm.compiler.lir.LIRInstructionClass;
@ -33,6 +34,7 @@ import org.graalvm.compiler.lir.amd64.AMD64Call.DirectCallOp;
import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind;
import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.meta.Value;
@ -45,11 +47,13 @@ final class AMD64HotSpotDirectStaticCallOp extends DirectCallOp {
public static final LIRInstructionClass<AMD64HotSpotDirectStaticCallOp> TYPE = LIRInstructionClass.create(AMD64HotSpotDirectStaticCallOp.class);
private final InvokeKind invokeKind;
private final GraalHotSpotVMConfig config;
AMD64HotSpotDirectStaticCallOp(ResolvedJavaMethod target, Value result, Value[] parameters, Value[] temps, LIRFrameState state, InvokeKind invokeKind) {
AMD64HotSpotDirectStaticCallOp(ResolvedJavaMethod target, Value result, Value[] parameters, Value[] temps, LIRFrameState state, InvokeKind invokeKind, GraalHotSpotVMConfig config) {
super(TYPE, target, result, parameters, temps, state);
assert invokeKind.isDirect();
this.invokeKind = invokeKind;
this.config = config;
}
@Override
@ -57,6 +61,9 @@ final class AMD64HotSpotDirectStaticCallOp extends DirectCallOp {
public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
try (CompilationResultBuilder.CallContext callContext = crb.openCallContext(invokeKind.isDirect())) {
crb.recordMark(invokeKind == InvokeKind.Static ? HotSpotMarkId.INVOKESTATIC : HotSpotMarkId.INVOKESPECIAL);
if (config.supportsMethodHandleDeoptimizationEntry() && config.isMethodHandleCall((HotSpotResolvedJavaMethod) callTarget) && invokeKind != InvokeKind.Static) {
crb.setNeedsMHDeoptHandler();
}
super.emitCode(crb, masm);
}
}

View File

@ -24,6 +24,7 @@
package org.graalvm.compiler.hotspot.amd64;
import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
import static org.graalvm.compiler.hotspot.HotSpotBackend.Options.GraalArithmeticStubs;
import org.graalvm.compiler.core.amd64.AMD64LoweringProviderMixin;
@ -70,10 +71,8 @@ public class AMD64HotSpotLoweringProvider extends DefaultHotSpotLoweringProvider
@Override
public void initialize(OptionValues options, Iterable<DebugHandlersFactory> factories, HotSpotProviders providers, GraalHotSpotVMConfig config) {
convertSnippets = new AMD64ConvertSnippets.Templates(options, factories, providers, providers.getSnippetReflection(), providers.getCodeCache().getTarget());
if (JavaVersionUtil.JAVA_SPEC <= 8) {
if (JavaVersionUtil.JAVA_SPEC >= 11 && GeneratePIC.getValue(options)) {
// AOT only introduced in JDK 9
profileSnippets = null;
} else {
profileSnippets = new ProbabilisticProfileSnippets.Templates(options, factories, providers, providers.getCodeCache().getTarget());
}
mathSnippets = new AMD64X87MathSnippets.Templates(options, factories, providers, providers.getSnippetReflection(), providers.getCodeCache().getTarget());

View File

@ -142,7 +142,7 @@ public class AMD64HotSpotNodeLIRBuilder extends AMD64NodeLIRBuilder implements H
assert invokeKind.isDirect();
HotSpotResolvedJavaMethod resolvedMethod = (HotSpotResolvedJavaMethod) callTarget.targetMethod();
assert resolvedMethod.isConcrete() : "Cannot make direct call to abstract method.";
append(new AMD64HotSpotDirectStaticCallOp(callTarget.targetMethod(), result, parameters, temps, callState, invokeKind));
append(new AMD64HotSpotDirectStaticCallOp(callTarget.targetMethod(), result, parameters, temps, callState, invokeKind, getGen().config));
}
}

View File

@ -35,6 +35,7 @@ import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind;
import jdk.vm.ci.amd64.AMD64;
import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.meta.Value;
@ -65,6 +66,9 @@ final class AMD64HotspotDirectVirtualCallOp extends DirectCallOp {
crb.recordMark(invokeKind == InvokeKind.Virtual ? HotSpotMarkId.INVOKEVIRTUAL : HotSpotMarkId.INVOKEINTERFACE);
// This must be emitted exactly like this to ensure it's patchable
masm.movq(AMD64.rax, config.nonOopBits);
if (config.supportsMethodHandleDeoptimizationEntry() && config.isMethodHandleCall((HotSpotResolvedJavaMethod) callTarget)) {
crb.setNeedsMHDeoptHandler();
}
super.emitCall(crb, masm);
}
}

View File

@ -378,9 +378,11 @@ public class CheckGraalIntrinsics extends GraalTest {
}
if (isJDK10OrHigher()) {
if (!(arch instanceof AArch64)) {
add(toBeInvestigated,
"java/lang/Math.multiplyHigh(JJ)J");
}
}
if (isJDK11OrHigher()) {
// Relevant for Java flight recorder
@ -397,9 +399,12 @@ public class CheckGraalIntrinsics extends GraalTest {
}
if (isJDK13OrHigher()) {
if (!(arch instanceof AArch64)) {
add(toBeInvestigated,
"java/lang/Math.abs(I)I",
"java/lang/Math.abs(J)J",
"java/lang/Math.abs(J)J");
}
add(toBeInvestigated,
"java/lang/Math.max(DD)D",
"java/lang/Math.max(FF)F",
"java/lang/Math.min(DD)D",

View File

@ -1102,7 +1102,7 @@ public final class CompileTheWorld {
public static final OptionKey<String> Config = new OptionKey<>(null);
public static final OptionKey<Boolean> MultiThreaded = new OptionKey<>(false);
public static final OptionKey<Integer> Threads = new OptionKey<>(0);
public static final OptionKey<Boolean> InvalidateInstalledCode = new OptionKey<>(false);
public static final OptionKey<Boolean> InvalidateInstalledCode = new OptionKey<>(true);
// @formatter:off
static final ReflectionOptionDescriptors DESCRIPTORS = new ReflectionOptionDescriptors(Options.class,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,6 +25,7 @@
package org.graalvm.compiler.hotspot;
import org.graalvm.compiler.core.phases.CommunityCompilerConfiguration;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.phases.tiers.CompilerConfiguration;
import org.graalvm.compiler.serviceprovider.ServiceProvider;
@ -50,4 +51,9 @@ public class CommunityCompilerConfigurationFactory extends CompilerConfiguration
public CompilerConfiguration createCompilerConfiguration() {
return new CommunityCompilerConfiguration();
}
@Override
public Instrumentation createInstrumentation(OptionValues options) {
return new DefaultInstrumentation();
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -96,6 +96,8 @@ public abstract class CompilerConfigurationFactory implements Comparable<Compile
public abstract CompilerConfiguration createCompilerConfiguration();
public abstract Instrumentation createInstrumentation(OptionValues options);
/**
* Collect the set of available {@linkplain HotSpotBackendFactory backends} for this compiler
* configuration.

View File

@ -0,0 +1,31 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.graalvm.compiler.hotspot;
/**
* Default version of {@link Instrumentation}.
*/
public class DefaultInstrumentation implements Instrumentation {
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,6 +25,7 @@
package org.graalvm.compiler.hotspot;
import org.graalvm.compiler.core.phases.EconomyCompilerConfiguration;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.phases.tiers.CompilerConfiguration;
import org.graalvm.compiler.serviceprovider.ServiceProvider;
@ -52,4 +53,9 @@ public class EconomyCompilerConfigurationFactory extends CompilerConfigurationFa
// the economy configuration only differs in the frontend, it reuses the "community" backend
return new DefaultBackendMap(CommunityCompilerConfigurationFactory.NAME);
}
@Override
public Instrumentation createInstrumentation(OptionValues options) {
return new DefaultInstrumentation();
}
}

View File

@ -28,6 +28,8 @@ import static jdk.vm.ci.runtime.JVMCI.getRuntime;
import static jdk.vm.ci.services.Services.IS_IN_NATIVE_IMAGE;
import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING;
import java.util.function.Consumer;
import jdk.internal.vm.compiler.collections.UnmodifiableEconomicMap;
import org.graalvm.compiler.api.runtime.GraalJVMCICompiler;
import org.graalvm.compiler.api.runtime.GraalRuntime;
@ -51,7 +53,6 @@ import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.phases.util.Providers;
import org.graalvm.compiler.replacements.ConstantBindingParameterPlugin;
import org.graalvm.compiler.replacements.PEGraphDecoder;
import org.graalvm.compiler.replacements.ReplacementsImpl;
import jdk.vm.ci.meta.ResolvedJavaField;
import jdk.vm.ci.meta.ResolvedJavaMethod;
@ -61,52 +62,54 @@ import jdk.vm.ci.meta.UnresolvedJavaMethod;
import jdk.vm.ci.meta.UnresolvedJavaType;
public class EncodedSnippets {
static class GraphData {
int startOffset;
String originalMethod;
SnippetParameterInfo info;
GraphData(int startOffset, String originalMethod, SnippetParameterInfo info) {
this.startOffset = startOffset;
this.originalMethod = originalMethod;
this.info = info;
}
}
private final byte[] snippetEncoding;
private final Object[] snippetObjects;
private final NodeClass<?>[] snippetNodeClasses;
private final UnmodifiableEconomicMap<String, Integer> snippetStartOffsets;
private final UnmodifiableEconomicMap<String, String> originalMethods;
private UnmodifiableEconomicMap<String, SnippetParameterInfo> snippetParameterInfos;
private final UnmodifiableEconomicMap<String, GraphData> graphDatas;
EncodedSnippets(byte[] snippetEncoding, Object[] snippetObjects, NodeClass<?>[] snippetNodeClasses, UnmodifiableEconomicMap<String, Integer> snippetStartOffsets,
UnmodifiableEconomicMap<String, String> originalMethods, UnmodifiableEconomicMap<String, SnippetParameterInfo> snippetParameterInfos) {
EncodedSnippets(byte[] snippetEncoding, Object[] snippetObjects, NodeClass<?>[] snippetNodeClasses, UnmodifiableEconomicMap<String, GraphData> graphDatas) {
this.snippetEncoding = snippetEncoding;
this.snippetObjects = snippetObjects;
this.snippetNodeClasses = snippetNodeClasses;
this.snippetStartOffsets = snippetStartOffsets;
this.originalMethods = originalMethods;
this.snippetParameterInfos = snippetParameterInfos;
}
public byte[] getSnippetEncoding() {
return snippetEncoding;
this.graphDatas = graphDatas;
}
public NodeClass<?>[] getSnippetNodeClasses() {
return snippetNodeClasses;
}
public UnmodifiableEconomicMap<String, Integer> getSnippetStartOffsets() {
return snippetStartOffsets;
public void visitImmutable(Consumer<Object> visitor) {
visitor.accept(snippetEncoding);
visitor.accept(snippetNodeClasses);
visitor.accept(graphDatas);
}
public UnmodifiableEconomicMap<String, String> getOriginalMethods() {
return originalMethods;
}
StructuredGraph getMethodSubstitutionGraph(MethodSubstitutionPlugin plugin, ResolvedJavaMethod original, ReplacementsImpl replacements, IntrinsicContext.CompilationContext context,
StructuredGraph getMethodSubstitutionGraph(MethodSubstitutionPlugin plugin, ResolvedJavaMethod original, HotSpotReplacementsImpl replacements, IntrinsicContext.CompilationContext context,
StructuredGraph.AllowAssumptions allowAssumptions, Cancellable cancellable, OptionValues options) {
IntrinsicContext.CompilationContext contextToUse = context;
if (context == IntrinsicContext.CompilationContext.ROOT_COMPILATION) {
contextToUse = IntrinsicContext.CompilationContext.ROOT_COMPILATION_ENCODING;
}
Integer startOffset = snippetStartOffsets.get(plugin.toString() + contextToUse);
if (startOffset == null) {
GraphData data = graphDatas.get(plugin.toString() + contextToUse);
if (data == null) {
throw GraalError.shouldNotReachHere("plugin graph not found: " + plugin + " with " + contextToUse);
}
ResolvedJavaType accessingClass = replacements.getProviders().getMetaAccess().lookupJavaType(plugin.getDeclaringClass());
return decodeGraph(original, accessingClass, startOffset, replacements, contextToUse, allowAssumptions, cancellable, options);
return decodeGraph(original, accessingClass, data.startOffset, replacements, contextToUse, allowAssumptions, cancellable, options);
}
/**
@ -121,7 +124,7 @@ public class EncodedSnippets {
private StructuredGraph decodeGraph(ResolvedJavaMethod method,
ResolvedJavaType accessingClass,
int startOffset,
ReplacementsImpl replacements,
HotSpotReplacementsImpl replacements,
IntrinsicContext.CompilationContext context,
StructuredGraph.AllowAssumptions allowAssumptions,
Cancellable cancellable,
@ -129,24 +132,23 @@ public class EncodedSnippets {
Providers providers = replacements.getProviders();
EncodedGraph encodedGraph = new SymbolicEncodedGraph(snippetEncoding, startOffset, snippetObjects, snippetNodeClasses,
methodKey(method), accessingClass, method.getDeclaringClass());
try (DebugContext debug = replacements.openDebugContext("SVMSnippet_", method, options)) {
boolean isSubstitution = true;
StructuredGraph result = new StructuredGraph.Builder(options, debug, allowAssumptions).cancellable(cancellable).method(method).setIsSubstitution(isSubstitution).build();
PEGraphDecoder graphDecoder = new SubstitutionGraphDecoder(providers, result, replacements, null, method, context, encodedGraph);
try (DebugContext debug = replacements.openSnippetDebugContext("LibgraalSnippet_", method, options)) {
StructuredGraph result = new StructuredGraph.Builder(options, debug, allowAssumptions).cancellable(cancellable).method(method).setIsSubstitution(true).build();
PEGraphDecoder graphDecoder = new SubstitutionGraphDecoder(providers, result, replacements, null, method, context, encodedGraph, true);
graphDecoder.decode(method, isSubstitution, encodedGraph.trackNodeSourcePosition());
graphDecoder.decode(method, result.isSubstitution(), encodedGraph.trackNodeSourcePosition());
assert result.verify();
return result;
}
}
StructuredGraph getEncodedSnippet(ResolvedJavaMethod method, ReplacementsImpl replacements, Object[] args, StructuredGraph.AllowAssumptions allowAssumptions, OptionValues options) {
Integer startOffset = null;
if (snippetStartOffsets != null) {
startOffset = snippetStartOffsets.get(methodKey(method));
StructuredGraph getEncodedSnippet(ResolvedJavaMethod method, HotSpotReplacementsImpl replacements, Object[] args, StructuredGraph.AllowAssumptions allowAssumptions, OptionValues options) {
GraphData data = null;
if (graphDatas != null) {
data = graphDatas.get(methodKey(method));
}
if (startOffset == null) {
if (data == null) {
if (IS_IN_NATIVE_IMAGE) {
throw GraalError.shouldNotReachHere("snippet not found: " + method.format("%H.%n(%p)"));
} else {
@ -154,31 +156,39 @@ public class EncodedSnippets {
}
}
SymbolicEncodedGraph encodedGraph = new SymbolicEncodedGraph(snippetEncoding, startOffset, snippetObjects, snippetNodeClasses,
originalMethods.get(methodKey(method)), method.getDeclaringClass());
return decodeSnippetGraph(encodedGraph, method, replacements, args, allowAssumptions, options);
SymbolicEncodedGraph encodedGraph = new SymbolicEncodedGraph(snippetEncoding, data.startOffset, snippetObjects, snippetNodeClasses, data.originalMethod, method.getDeclaringClass());
return decodeSnippetGraph(encodedGraph, method, replacements, args, allowAssumptions, options, IS_IN_NATIVE_IMAGE);
}
public SnippetParameterInfo getSnippetParameterInfo(ResolvedJavaMethod method) {
SnippetParameterInfo info = snippetParameterInfos.get(methodKey(method));
GraphData data = null;
if (graphDatas != null) {
data = graphDatas.get(methodKey(method));
}
assert data != null : method;
SnippetParameterInfo info = data.info;
assert info != null;
return info;
}
public boolean isSnippet(ResolvedJavaMethod method) {
return snippetParameterInfos.get(methodKey(method)) != null;
GraphData data = null;
if (graphDatas != null) {
data = graphDatas.get(methodKey(method));
}
return data != null && data.info != null;
}
@SuppressWarnings("try")
private static StructuredGraph decodeSnippetGraph(SymbolicEncodedGraph encodedGraph, ResolvedJavaMethod method, ReplacementsImpl replacements, Object[] args,
StructuredGraph.AllowAssumptions allowAssumptions, OptionValues options) {
static StructuredGraph decodeSnippetGraph(SymbolicEncodedGraph encodedGraph, ResolvedJavaMethod method, HotSpotReplacementsImpl replacements, Object[] args,
StructuredGraph.AllowAssumptions allowAssumptions, OptionValues options, boolean mustSucceed) {
Providers providers = replacements.getProviders();
ParameterPlugin parameterPlugin = null;
if (args != null) {
parameterPlugin = new ConstantBindingParameterPlugin(args, providers.getMetaAccess(), replacements.snippetReflection);
}
try (DebugContext debug = replacements.openDebugContext("SVMSnippet_", method, options)) {
try (DebugContext debug = replacements.openSnippetDebugContext("SVMSnippet_", method, options)) {
// @formatter:off
boolean isSubstitution = true;
StructuredGraph result = new StructuredGraph.Builder(options, debug, allowAssumptions)
@ -188,7 +198,7 @@ public class EncodedSnippets {
.build();
// @formatter:on
try (DebugContext.Scope scope = debug.scope("DecodeSnippetGraph", result)) {
PEGraphDecoder graphDecoder = new SubstitutionGraphDecoder(providers, result, replacements, parameterPlugin, method, INLINE_AFTER_PARSING, encodedGraph);
PEGraphDecoder graphDecoder = new SubstitutionGraphDecoder(providers, result, replacements, parameterPlugin, method, INLINE_AFTER_PARSING, encodedGraph, mustSucceed);
graphDecoder.decode(method, isSubstitution, encodedGraph.trackNodeSourcePosition());
debug.dump(DebugContext.VERBOSE_LEVEL, result, "After decoding");
@ -201,18 +211,20 @@ public class EncodedSnippets {
}
}
public static class SubstitutionGraphDecoder extends PEGraphDecoder {
static class SubstitutionGraphDecoder extends PEGraphDecoder {
private final ResolvedJavaMethod method;
private final EncodedGraph encodedGraph;
private IntrinsicContext intrinsic;
private final boolean mustSucceed;
SubstitutionGraphDecoder(Providers providers, StructuredGraph result, ReplacementsImpl replacements, ParameterPlugin parameterPlugin, ResolvedJavaMethod method,
IntrinsicContext.CompilationContext context, EncodedGraph encodedGraph) {
SubstitutionGraphDecoder(Providers providers, StructuredGraph result, HotSpotReplacementsImpl replacements, ParameterPlugin parameterPlugin, ResolvedJavaMethod method,
IntrinsicContext.CompilationContext context, EncodedGraph encodedGraph, boolean mustSucceed) {
super(providers.getCodeCache().getTarget().arch, result, providers, null,
replacements.getGraphBuilderPlugins().getInvocationPlugins(), new InlineInvokePlugin[0], parameterPlugin,
null, null, null);
this.method = method;
this.encodedGraph = encodedGraph;
this.mustSucceed = mustSucceed;
intrinsic = new IntrinsicContext(method, null, replacements.getDefaultReplacementBytecodeProvider(), context, false);
}
@ -230,9 +242,14 @@ public class EncodedSnippets {
}
@Override
protected IntrinsicContext getIntrinsic() {
public IntrinsicContext getIntrinsic() {
return intrinsic;
}
@Override
protected boolean pluginReplacementMustSucceed() {
return mustSucceed;
}
}
static class SymbolicEncodedGraph extends EncodedGraph {

View File

@ -886,6 +886,7 @@ public class GraalHotSpotVMConfig extends GraalHotSpotVMConfigAccess {
public final int OSR_ENTRY = getConstant("CodeInstaller::OSR_ENTRY", Integer.class);
public final int EXCEPTION_HANDLER_ENTRY = getConstant("CodeInstaller::EXCEPTION_HANDLER_ENTRY", Integer.class);
public final int DEOPT_HANDLER_ENTRY = getConstant("CodeInstaller::DEOPT_HANDLER_ENTRY", Integer.class);
public final int DEOPT_MH_HANDLER_ENTRY = getConstant("CodeInstaller::DEOPT_MH_HANDLER_ENTRY", Integer.class, -1, (JVMCI ? jvmciGE(JVMCI_20_2_b01) : false));
public final int FRAME_COMPLETE = getConstant("CodeInstaller::FRAME_COMPLETE", Integer.class, -1, (JVMCI ? jvmciGE(JVMCI_20_1_b01) : JDK_8245443));
public final int INVOKEINTERFACE = getConstant("CodeInstaller::INVOKEINTERFACE", Integer.class);
public final int INVOKEVIRTUAL = getConstant("CodeInstaller::INVOKEVIRTUAL", Integer.class);
@ -899,6 +900,10 @@ public class GraalHotSpotVMConfig extends GraalHotSpotVMConfigAccess {
public final int CARD_TABLE_SHIFT = getConstant("CodeInstaller::CARD_TABLE_SHIFT", Integer.class);
public final int CARD_TABLE_ADDRESS = getConstant("CodeInstaller::CARD_TABLE_ADDRESS", Integer.class);
public final int INVOKE_INVALID = getConstant("CodeInstaller::INVOKE_INVALID", Integer.class);
public final int VMINTRINSIC_FIRST_MH_SIG_POLY = getConstant("vmIntrinsics::FIRST_MH_SIG_POLY", Integer.class, -1, (JVMCI ? jvmciGE(JVMCI_20_2_b01) : false));
public final int VMINTRINSIC_LAST_MH_SIG_POLY = getConstant("vmIntrinsics::LAST_MH_SIG_POLY", Integer.class, -1, (JVMCI ? jvmciGE(JVMCI_20_2_b01) : false));
public final int VMINTRINSIC_INVOKE_GENERIC = getConstant("vmIntrinsics::_invokeGeneric", Integer.class, -1, (JVMCI ? jvmciGE(JVMCI_20_2_b01) : false));
public final int VMINTRINSIC_COMPILED_LAMBDA_FORM = getConstant("vmIntrinsics::_compiledLambdaForm", Integer.class, -1, (JVMCI ? jvmciGE(JVMCI_20_2_b01) : false));
public final boolean CPU_HAS_INTEL_JCC_ERRATUM = getFieldValue("VM_Version::_has_intel_jcc_erratum", Boolean.class, "bool",
true, "amd64".equals(osArch) && (JVMCI ? jvmciGE(JVMCI_20_1_b01) : JDK >= 15));
@ -926,4 +931,17 @@ public class GraalHotSpotVMConfig extends GraalHotSpotVMConfigAccess {
assert checkNullAllocationStubs();
return true;
}
public boolean isMethodHandleCall(HotSpotResolvedJavaMethod targetMethod) {
int intrinsicId = targetMethod.intrinsicId();
return ((intrinsicId >= VMINTRINSIC_FIRST_MH_SIG_POLY && intrinsicId <= VMINTRINSIC_LAST_MH_SIG_POLY) // MethodHandles::is_signature_polymorphic
&& intrinsicId != VMINTRINSIC_INVOKE_GENERIC) // MethodHandles::is_signature_polymorphic_intrinsic
|| intrinsicId == VMINTRINSIC_COMPILED_LAMBDA_FORM; // ciMethod::is_compiled_lambda_form
}
public boolean supportsMethodHandleDeoptimizationEntry() {
return DEOPT_MH_HANDLER_ENTRY != -1 && VMINTRINSIC_FIRST_MH_SIG_POLY != -1 && VMINTRINSIC_LAST_MH_SIG_POLY != -1 && VMINTRINSIC_INVOKE_GENERIC != -1 &&
VMINTRINSIC_COMPILED_LAMBDA_FORM != -1;
}
}

View File

@ -127,6 +127,7 @@ public class GraalHotSpotVMConfigAccess {
public final String osArch;
protected static final Version JVMCI_0_55 = new Version2(0, 55);
protected static final Version JVMCI_20_2_b01 = new Version3(20, 2, 1);
protected static final Version JVMCI_20_1_b01 = new Version3(20, 1, 1);
protected static final Version JVMCI_20_0_b03 = new Version3(20, 0, 3);
protected static final Version JVMCI_19_3_b03 = new Version3(19, 3, 3);

View File

@ -26,13 +26,13 @@ package org.graalvm.compiler.hotspot;
import org.graalvm.compiler.bytecode.BytecodeProvider;
import org.graalvm.compiler.hotspot.meta.HotSpotGraalConstantFieldProvider;
import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
import org.graalvm.compiler.hotspot.meta.HotSpotMetaAccessExtensionProvider;
import org.graalvm.compiler.hotspot.meta.HotSpotPlatformConfigurationProvider;
import org.graalvm.compiler.hotspot.meta.HotSpotSnippetReflectionProvider;
import org.graalvm.compiler.hotspot.meta.HotSpotStampProvider;
import org.graalvm.compiler.hotspot.word.HotSpotWordTypes;
import org.graalvm.compiler.phases.tiers.CompilerConfiguration;
import org.graalvm.compiler.phases.util.Providers;
import org.graalvm.compiler.replacements.classfile.ClassfileBytecodeProvider;
import jdk.vm.ci.code.Architecture;
@ -64,7 +64,7 @@ public abstract class HotSpotBackendFactory {
return new HotSpotMetaAccessExtensionProvider();
}
protected HotSpotReplacementsImpl createReplacements(TargetDescription target, Providers p, HotSpotSnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider) {
protected HotSpotReplacementsImpl createReplacements(TargetDescription target, HotSpotProviders p, HotSpotSnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider) {
return new HotSpotReplacementsImpl(p, snippetReflection, bytecodeProvider, target);
}

View File

@ -24,20 +24,22 @@
package org.graalvm.compiler.hotspot;
import static jdk.vm.ci.common.InitTimer.timer;
import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
import static org.graalvm.compiler.core.common.GraalOptions.HotSpotPrintInlining;
import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigAccess.JDK;
import java.io.PrintStream;
import java.util.ArrayList;
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.vm.ci.code.Architecture;
import jdk.vm.ci.code.stack.StackIntrospection;
import jdk.vm.ci.common.InitTimer;
import jdk.vm.ci.hotspot.HotSpotCompilationRequest;
import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
import jdk.vm.ci.hotspot.HotSpotResolvedJavaType;
import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
import jdk.vm.ci.hotspot.HotSpotVMConfigStore;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.MetaAccessProvider;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.meta.ResolvedJavaType;
import jdk.vm.ci.runtime.JVMCI;
import jdk.vm.ci.runtime.JVMCIBackend;
import jdk.vm.ci.services.Services;
import jdk.internal.vm.compiler.collections.EconomicMap;
import jdk.internal.vm.compiler.collections.EconomicSet;
import jdk.internal.vm.compiler.collections.Equivalence;
@ -78,22 +80,19 @@ import org.graalvm.compiler.replacements.SnippetCounter.Group;
import org.graalvm.compiler.runtime.RuntimeProvider;
import org.graalvm.compiler.serviceprovider.GraalServices;
import jdk.vm.ci.code.Architecture;
import jdk.vm.ci.code.stack.StackIntrospection;
import jdk.vm.ci.common.InitTimer;
import jdk.vm.ci.hotspot.HotSpotCompilationRequest;
import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
import jdk.vm.ci.hotspot.HotSpotResolvedJavaType;
import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
import jdk.vm.ci.hotspot.HotSpotVMConfigStore;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.MetaAccessProvider;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.meta.ResolvedJavaType;
import jdk.vm.ci.runtime.JVMCI;
import jdk.vm.ci.runtime.JVMCIBackend;
import jdk.vm.ci.services.Services;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Supplier;
import static jdk.vm.ci.common.InitTimer.timer;
import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
import static org.graalvm.compiler.core.common.GraalOptions.HotSpotPrintInlining;
import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigAccess.JDK;
//JaCoCo Exclude
@ -138,6 +137,8 @@ public final class HotSpotGraalRuntime implements HotSpotGraalRuntimeProvider {
private final GraalHotSpotVMConfig config;
private final Instrumentation instrumentation;
/**
* The options can be {@linkplain #setOptionValues(String[], String[]) updated} by external
* interfaces such as JMX. This comes with the risk that inconsistencies can arise as an
@ -178,6 +179,8 @@ public final class HotSpotGraalRuntime implements HotSpotGraalRuntimeProvider {
CompilerConfiguration compilerConfiguration = compilerConfigurationFactory.createCompilerConfiguration();
compilerConfigurationName = compilerConfigurationFactory.getName();
this.instrumentation = compilerConfigurationFactory.createInstrumentation(options);
if (IS_AOT) {
management = AOT_INJECTED_MANAGEMENT == null ? null : AOT_INJECTED_MANAGEMENT.get();
} else {
@ -427,6 +430,11 @@ public final class HotSpotGraalRuntime implements HotSpotGraalRuntimeProvider {
return compilerConfigurationName;
}
@Override
public Instrumentation getInstrumentation() {
return instrumentation;
}
private long runtimeStartTime;
/**
@ -492,7 +500,7 @@ public final class HotSpotGraalRuntime implements HotSpotGraalRuntimeProvider {
/**
* Substituted by
* {@code com.oracle.svm.graal.hotspot.libgraal.Target_org_graalvm_compiler_hotspot_HotSpotGraalRuntime}
* to call {@code org.graalvm.nativeimage.VMRuntime.shutdown()}.
* to call {@code jdk.internal.vm.compiler.nativeimage.VMRuntime.shutdown()}.
*/
private static void shutdownLibGraal() {
}

View File

@ -107,4 +107,9 @@ public interface HotSpotGraalRuntimeProvider extends GraalRuntime, RuntimeProvid
* which configuration is in use.
*/
String getCompilerConfigurationName();
/**
* Returns the instance holding the instrumentation data structures.
*/
Instrumentation getInstrumentation();
}

View File

@ -101,7 +101,7 @@ public abstract class HotSpotHostBackend extends HotSpotBackend implements LIRGe
@SuppressWarnings("try")
public void completeInitialization(HotSpotJVMCIRuntime jvmciRuntime, OptionValues options) {
final HotSpotProviders providers = getProviders();
HotSpotHostForeignCallsProvider foreignCalls = (HotSpotHostForeignCallsProvider) providers.getForeignCalls();
HotSpotHostForeignCallsProvider foreignCalls = providers.getForeignCalls();
final HotSpotLoweringProvider lowerer = (HotSpotLoweringProvider) providers.getLowerer();
try (InitTimer st = timer("foreignCalls.initialize")) {

View File

@ -42,6 +42,7 @@ public enum HotSpotMarkId implements CompilationResult.MarkId {
OSR_ENTRY(false),
EXCEPTION_HANDLER_ENTRY(false),
DEOPT_HANDLER_ENTRY(false),
DEOPT_MH_HANDLER_ENTRY(false),
FRAME_COMPLETE(true, true),
INVOKEINTERFACE(false),
INVOKEVIRTUAL(false),

View File

@ -37,6 +37,7 @@ import org.graalvm.compiler.core.common.CompilationIdentifier;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.graph.NodeSourcePosition;
import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
import org.graalvm.compiler.hotspot.meta.HotSpotWordOperationPlugin;
import org.graalvm.compiler.hotspot.word.HotSpotOperation;
import org.graalvm.compiler.nodes.Cancellable;
@ -50,7 +51,6 @@ import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin;
import org.graalvm.compiler.nodes.graphbuilderconf.MethodSubstitutionPlugin;
import org.graalvm.compiler.nodes.spi.SnippetParameterInfo;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.phases.util.Providers;
import org.graalvm.compiler.printer.GraalDebugHandlersFactory;
import org.graalvm.compiler.replacements.ReplacementsImpl;
@ -63,15 +63,20 @@ import jdk.vm.ci.meta.ResolvedJavaMethod;
* them.
*/
public class HotSpotReplacementsImpl extends ReplacementsImpl {
public HotSpotReplacementsImpl(Providers providers, SnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider, TargetDescription target) {
public HotSpotReplacementsImpl(HotSpotProviders providers, SnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider, TargetDescription target) {
super(new GraalDebugHandlersFactory(snippetReflection), providers, snippetReflection, bytecodeProvider, target);
}
HotSpotReplacementsImpl(HotSpotReplacementsImpl replacements, Providers providers) {
HotSpotReplacementsImpl(HotSpotReplacementsImpl replacements, HotSpotProviders providers) {
super(new GraalDebugHandlersFactory(replacements.snippetReflection), providers, replacements.snippetReflection,
replacements.getDefaultReplacementBytecodeProvider(), replacements.target);
}
@Override
public HotSpotProviders getProviders() {
return (HotSpotProviders) super.getProviders();
}
public void maybeInitializeEncoder(OptionValues options) {
if (IS_IN_NATIVE_IMAGE) {
return;
@ -85,14 +90,6 @@ public class HotSpotReplacementsImpl extends ReplacementsImpl {
}
}
/**
* Returns true if this Replacements is being used for preparation of snippets and substitutions
* for libgraal.
*/
public boolean isEncodingSnippets() {
return false;
}
@Override
public Class<? extends GraphBuilderPlugin> getIntrinsifyingPlugin(ResolvedJavaMethod method) {
if (!IS_IN_NATIVE_IMAGE) {
@ -189,6 +186,7 @@ public class HotSpotReplacementsImpl extends ReplacementsImpl {
@Override
public void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, boolean trackNodeSourcePosition, OptionValues options) {
assert method.isStatic() || receiver != null : "must have a constant type for the receiver";
if (!IS_IN_NATIVE_IMAGE) {
assert !snippetRegistrationClosed : "Cannot register snippet after registration is closed: " + method.format("%H.%n(%p)");
assert registeredSnippets.add(method) : "Cannot register snippet twice: " + method.format("%H.%n(%p)");
@ -303,4 +301,12 @@ public class HotSpotReplacementsImpl extends ReplacementsImpl {
return null;
}
@SuppressWarnings("unchecked")
@Override
public <T> T getInjectedArgument(Class<T> capability) {
if (capability.equals(GraalHotSpotVMConfig.class)) {
return (T) getProviders().getConfig();
}
return super.getInjectedArgument(capability);
}
}

View File

@ -0,0 +1,31 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.graalvm.compiler.hotspot;
/**
* Interface in charge of holding the instrumentation data structures.
*/
public interface Instrumentation {
}

View File

@ -43,7 +43,7 @@ import java.util.regex.Pattern;
*/
public final class JVMCIVersionCheck {
private static final Version JVMCI_MIN_VERSION = new Version3(20, 1, 2);
private static final Version JVMCI_MIN_VERSION = new Version3(20, 2, 1);
public interface Version {
boolean isLessThan(Version other);
@ -180,6 +180,9 @@ public final class JVMCIVersionCheck {
}
}
public static final String JVMCI8_RELEASES_URL = "https://github.com/graalvm/graal-jvmci-8/releases";
public static final String JVMCI11_RELEASES_URL = "https://github.com/graalvm/labs-openjdk-11/releases";
private void failVersionCheck(boolean exit, String reason, Object... args) {
Formatter errorMessage = new Formatter().format(reason, args);
String javaHome = props.get("java.home");
@ -189,10 +192,10 @@ public final class JVMCIVersionCheck {
errorMessage.format("Currently used Java home directory is %s.%n", javaHome);
errorMessage.format("Currently used VM configuration is: %s%n", vmName);
if (javaSpecVersion.compareTo("1.9") < 0) {
errorMessage.format("Download the latest JVMCI JDK 8 from https://github.com/graalvm/openjdk8-jvmci-builder/releases");
errorMessage.format("Download the latest JVMCI JDK 8 from " + JVMCI8_RELEASES_URL);
} else {
if (javaSpecVersion.compareTo("11") == 0 && vmVersion.contains("-jvmci-")) {
errorMessage.format("Download the latest Labs OpenJDK 11 from https://github.com/graalvm/labs-openjdk-11/releases");
errorMessage.format("Download the latest Labs OpenJDK 11 from " + JVMCI11_RELEASES_URL);
} else {
errorMessage.format("Download JDK 11 or later.");
}

View File

@ -56,7 +56,6 @@ import org.graalvm.compiler.core.common.type.SymbolicJVMCIReference;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.graph.NodeMap;
import org.graalvm.compiler.graph.NodeSourcePosition;
import org.graalvm.compiler.hotspot.EncodedSnippets.GraalCapability;
@ -67,6 +66,7 @@ import org.graalvm.compiler.hotspot.EncodedSnippets.SymbolicResolvedJavaMethodBy
import org.graalvm.compiler.hotspot.EncodedSnippets.SymbolicStampPair;
import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProvider;
import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
import org.graalvm.compiler.hotspot.word.HotSpotWordTypes;
import org.graalvm.compiler.java.BytecodeParser;
import org.graalvm.compiler.java.GraphBuilderPhase;
import org.graalvm.compiler.nodeinfo.Verbosity;
@ -90,17 +90,15 @@ import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin;
import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins;
import org.graalvm.compiler.nodes.graphbuilderconf.MethodSubstitutionPlugin;
import org.graalvm.compiler.nodes.graphbuilderconf.NodePlugin;
import org.graalvm.compiler.nodes.graphbuilderconf.ParameterPlugin;
import org.graalvm.compiler.nodes.java.AccessFieldNode;
import org.graalvm.compiler.nodes.java.MethodCallTargetNode;
import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.nodes.spi.SnippetParameterInfo;
import org.graalvm.compiler.nodes.virtual.VirtualObjectNode;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.phases.OptimisticOptimizations;
import org.graalvm.compiler.phases.schedule.SchedulePhase;
import org.graalvm.compiler.phases.util.Providers;
import org.graalvm.compiler.replacements.ConstantBindingParameterPlugin;
import org.graalvm.compiler.replacements.PEGraphDecoder;
import org.graalvm.compiler.replacements.ReplacementsImpl;
import org.graalvm.compiler.replacements.SnippetCounter;
import org.graalvm.compiler.replacements.SnippetIntegerHistogram;
@ -149,11 +147,109 @@ public class SymbolicSnippetEncoder {
*/
private int encodedGraphs = 0;
abstract static class GraphKey {
final ResolvedJavaMethod method;
final ResolvedJavaMethod original;
GraphKey(ResolvedJavaMethod method, ResolvedJavaMethod original) {
this.method = method;
this.original = original;
}
public abstract String keyString();
}
static class SnippetKey extends GraphKey {
SnippetKey(ResolvedJavaMethod method, ResolvedJavaMethod original) {
super(method, original);
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
SnippetKey that = (SnippetKey) o;
return Objects.equals(method, that.method) &&
Objects.equals(original, that.original);
}
@Override
public int hashCode() {
return Objects.hash(method, original);
}
@Override
public String keyString() {
return methodKey(method);
}
@Override
public String toString() {
return "SnippetKey{" +
"method=" + method +
", original=" + original +
'}';
}
}
static class MethodSubstitutionKey extends GraphKey {
final IntrinsicContext.CompilationContext context;
final MethodSubstitutionPlugin plugin;
MethodSubstitutionKey(ResolvedJavaMethod method, ResolvedJavaMethod original, IntrinsicContext.CompilationContext context, MethodSubstitutionPlugin plugin) {
super(method, original);
this.context = context;
this.plugin = plugin;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
MethodSubstitutionKey that = (MethodSubstitutionKey) o;
return Objects.equals(original, that.original) &&
context == that.context &&
Objects.equals(plugin, that.plugin);
}
@Override
public int hashCode() {
return Objects.hash(original, context, plugin);
}
@Override
public String keyString() {
return plugin.toString() + context;
}
@Override
public String toString() {
return "MethodSubstitutionKey{" +
"method=" + method +
", original=" + original +
", context=" + context +
", plugin=" + plugin +
'}';
}
}
/**
* All the graphs parsed so far.
*/
private EconomicMap<String, StructuredGraph> preparedSnippetGraphs = EconomicMap.create();
private EconomicMap<String, GraphKey> keyToMethod = EconomicMap.create();
private EconomicMap<String, SnippetParameterInfo> snippetParameterInfos = EconomicMap.create();
private EconomicSet<MethodSubstitutionPlugin> knownPlugins = EconomicSet.create();
@ -172,9 +268,8 @@ public class SymbolicSnippetEncoder {
}
public void clearSnippetParameterNames() {
MapCursor<String, SnippetParameterInfo> cursor = snippetParameterInfos.getEntries();
while (cursor.advance()) {
cursor.getValue().clearNames();
for (SnippetParameterInfo info : snippetParameterInfos.getValues()) {
info.clearNames();
}
}
@ -187,11 +282,6 @@ public class SymbolicSnippetEncoder {
return InlineInfo.DO_NOT_INLINE_NO_EXCEPTION;
}
if (snippetReplacements.getIntrinsifyingPlugin(method) != null) {
delayedInvocationPluginMethods.add(method);
return InlineInfo.DO_NOT_INLINE_NO_EXCEPTION;
}
// Force inlining when parsing replacements
return createIntrinsicInlineInfo(method, snippetReplacements.getDefaultReplacementBytecodeProvider());
}
@ -202,21 +292,6 @@ public class SymbolicSnippetEncoder {
}
}
public static class SnippetInvocationPlugins extends InvocationPlugins {
SnippetInvocationPlugins(InvocationPlugins invocationPlugins) {
super(invocationPlugins);
}
@Override
public InvocationPlugin lookupInvocation(ResolvedJavaMethod method) {
if (method.getAnnotation(Fold.class) != null) {
return null;
}
return super.lookupInvocation(method);
}
}
/**
* This plugin disables the snippet counter machinery.
*/
@ -246,12 +321,12 @@ public class SymbolicSnippetEncoder {
SymbolicSnippetEncoder(HotSpotReplacementsImpl replacements) {
this.originalReplacements = replacements;
GraphBuilderConfiguration.Plugins plugins = replacements.getGraphBuilderPlugins();
SnippetInvocationPlugins invocationPlugins = new SnippetInvocationPlugins(plugins.getInvocationPlugins());
InvocationPlugins invocationPlugins = plugins.getInvocationPlugins();
GraphBuilderConfiguration.Plugins copy = new GraphBuilderConfiguration.Plugins(plugins, invocationPlugins);
copy.clearInlineInvokePlugins();
copy.appendInlineInvokePlugin(new SnippetInlineInvokePlugin());
copy.appendNodePlugin(new SnippetCounterPlugin());
HotSpotProviders providers = (HotSpotProviders) replacements.getProviders().copyWith(new HotSpotSubstrateConstantReflectionProvider(replacements.getProviders().getConstantReflection()));
HotSpotProviders providers = replacements.getProviders().copyWith(new HotSpotSubstrateConstantReflectionProvider(replacements.getProviders().getConstantReflection()));
this.snippetReplacements = new HotSpotSnippetReplacementsImpl(replacements, providers.copyWith(copy));
this.snippetReplacements.setGraphBuilderPlugins(copy);
}
@ -278,8 +353,10 @@ public class SymbolicSnippetEncoder {
assert method.getAnnotation(MethodSubstitution.class) != null : "MethodSubstitution must be annotated with @" + MethodSubstitution.class.getSimpleName();
String originalMethodString = plugin.originalMethodAsString();
StructuredGraph subst = buildGraph(method, original, originalMethodString, null, true, false, context, options);
originalMethods.put(methodKey(method), originalMethodString);
preparedSnippetGraphs.put(plugin.toString() + context, subst);
MethodSubstitutionKey key = new MethodSubstitutionKey(method, original, context, plugin);
originalMethods.put(key.keyString(), originalMethodString);
preparedSnippetGraphs.put(key.keyString(), subst);
keyToMethod.put(key.keyString(), key);
}
private StructuredGraph buildGraph(ResolvedJavaMethod method, ResolvedJavaMethod original, String originalMethodString, Object receiver, boolean requireInlining, boolean trackNodeSourcePosition,
@ -300,7 +377,7 @@ public class SymbolicSnippetEncoder {
if (context == IntrinsicContext.CompilationContext.ROOT_COMPILATION) {
contextToUse = IntrinsicContext.CompilationContext.ROOT_COMPILATION_ENCODING;
}
try (DebugContext debug = openDebugContext("SymbolicSnippetEncoder_", method, options)) {
try (DebugContext debug = snippetReplacements.openSnippetDebugContext("SymbolicSnippetEncoder_", method, options)) {
StructuredGraph graph = snippetReplacements.makeGraph(debug, snippetReplacements.getDefaultReplacementBytecodeProvider(), method, args, original, trackNodeSourcePosition, null,
contextToUse);
@ -311,51 +388,19 @@ public class SymbolicSnippetEncoder {
throw GraalError.shouldNotReachHere("method " + callee.format("%H.%n") + " not inlined in snippet " + method.getName() + " (maybe not final?)");
}
}
assert verifySnippetEncodeDecode(debug, method, original, originalMethodString, trackNodeSourcePosition, graph);
assert verifySnippetEncodeDecode(debug, method, original, originalMethodString, args, trackNodeSourcePosition, graph);
debug.dump(DebugContext.VERBOSE_LEVEL, graph, "After buildGraph");
return graph;
}
}
@SuppressWarnings("try")
private static StructuredGraph decodeSnippetGraph(SymbolicEncodedGraph encodedGraph, ResolvedJavaMethod method, ReplacementsImpl replacements, Object[] args,
StructuredGraph.AllowAssumptions allowAssumptions, OptionValues options) {
Providers providers = replacements.getProviders();
ParameterPlugin parameterPlugin = null;
if (args != null) {
parameterPlugin = new ConstantBindingParameterPlugin(args, providers.getMetaAccess(), replacements.snippetReflection);
}
try (DebugContext debug = replacements.openDebugContext("SVMSnippet_", method, options)) {
// @formatter:off
boolean isSubstitution = true;
StructuredGraph result = new StructuredGraph.Builder(options, debug, allowAssumptions)
.method(method)
.trackNodeSourcePosition(encodedGraph.trackNodeSourcePosition())
.setIsSubstitution(isSubstitution)
.build();
// @formatter:on
try (DebugContext.Scope scope = debug.scope("DecodeSnippetGraph", result)) {
PEGraphDecoder graphDecoder = new EncodedSnippets.SubstitutionGraphDecoder(providers, result, replacements, parameterPlugin, method, INLINE_AFTER_PARSING, encodedGraph);
graphDecoder.decode(method, isSubstitution, encodedGraph.trackNodeSourcePosition());
debug.dump(DebugContext.VERBOSE_LEVEL, result, "After decoding");
assert result.verify();
return result;
} catch (Throwable t) {
throw debug.handle(t);
}
}
}
@SuppressWarnings("try")
private boolean verifySnippetEncodeDecode(DebugContext debug, ResolvedJavaMethod method, ResolvedJavaMethod original, String originalMethodString, boolean trackNodeSourcePosition,
private boolean verifySnippetEncodeDecode(DebugContext debug, ResolvedJavaMethod method, ResolvedJavaMethod original, String originalMethodString, Object[] args, boolean trackNodeSourcePosition,
StructuredGraph graph) {
// Verify the encoding and decoding process
EncodedGraph encodedGraph = GraphEncoder.encodeSingleGraph(graph, HotSpotJVMCIRuntime.runtime().getHostJVMCIBackend().getTarget().arch);
HotSpotProviders originalProvider = (HotSpotProviders) snippetReplacements.getProviders();
HotSpotProviders originalProvider = snippetReplacements.getProviders();
SnippetReflectionProvider snippetReflection = originalProvider.getSnippetReflection();
SymbolicSnippetEncoder.HotSpotSubstrateConstantReflectionProvider constantReflection = new SymbolicSnippetEncoder.HotSpotSubstrateConstantReflectionProvider(
@ -363,7 +408,7 @@ public class SymbolicSnippetEncoder {
HotSpotProviders newProviders = new HotSpotProviders(originalProvider.getMetaAccess(), originalProvider.getCodeCache(), constantReflection,
originalProvider.getConstantFieldProvider(), originalProvider.getForeignCalls(), originalProvider.getLowerer(), null, originalProvider.getSuites(),
originalProvider.getRegisters(), snippetReflection, originalProvider.getWordTypes(), originalProvider.getGraphBuilderPlugins(),
originalProvider.getPlatformConfigurationProvider(), originalProvider.getMetaAccessExtensionProvider());
originalProvider.getPlatformConfigurationProvider(), originalProvider.getMetaAccessExtensionProvider(), originalProvider.getConfig());
HotSpotSnippetReplacementsImpl filteringReplacements = new HotSpotSnippetReplacementsImpl(newProviders, snippetReflection,
originalProvider.getReplacements().getDefaultReplacementBytecodeProvider(), originalProvider.getCodeCache().getTarget());
filteringReplacements.setGraphBuilderPlugins(originalProvider.getReplacements().getGraphBuilderPlugins());
@ -371,11 +416,11 @@ public class SymbolicSnippetEncoder {
for (int i = 0; i < encodedGraph.getNumObjects(); i++) {
filterSnippetObject(encodedGraph.getObject(i));
}
StructuredGraph snippet = filteringReplacements.makeGraph(debug, filteringReplacements.getDefaultReplacementBytecodeProvider(), method, null, original,
StructuredGraph snippet = filteringReplacements.makeGraph(debug, filteringReplacements.getDefaultReplacementBytecodeProvider(), method, args, original,
trackNodeSourcePosition, null);
SymbolicEncodedGraph symbolicGraph = new SymbolicEncodedGraph(encodedGraph, method.getDeclaringClass(), originalMethodString);
StructuredGraph decodedSnippet = decodeSnippetGraph(symbolicGraph, original != null ? original : method, originalReplacements, null,
StructuredGraph.AllowAssumptions.ifNonNull(graph.getAssumptions()), graph.getOptions());
StructuredGraph decodedSnippet = EncodedSnippets.decodeSnippetGraph(symbolicGraph, original != null ? original : method, originalReplacements, null,
StructuredGraph.AllowAssumptions.ifNonNull(graph.getAssumptions()), graph.getOptions(), false);
String snippetString = getCanonicalGraphString(snippet, true, false);
String decodedSnippetString = getCanonicalGraphString(decodedSnippet, true, false);
if (snippetString.equals(decodedSnippetString)) {
@ -430,14 +475,16 @@ public class SymbolicSnippetEncoder {
synchronized void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, boolean trackNodeSourcePosition, OptionValues options) {
if (IS_BUILDING_NATIVE_IMAGE || UseEncodedGraphs.getValue(options)) {
assert method.getAnnotation(Snippet.class) != null : "Snippet must be annotated with @" + Snippet.class.getSimpleName();
String key = methodKey(method);
if (!preparedSnippetGraphs.containsKey(key)) {
SnippetKey key = new SnippetKey(method, original);
String keyString = key.keyString();
if (!preparedSnippetGraphs.containsKey(keyString)) {
if (original != null) {
originalMethods.put(key, methodKey(original));
originalMethods.put(keyString, methodKey(original));
}
StructuredGraph snippet = buildGraph(method, original, null, receiver, true, trackNodeSourcePosition, INLINE_AFTER_PARSING, options);
preparedSnippetGraphs.put(key, snippet);
snippetParameterInfos.put(key, new SnippetParameterInfo(method));
preparedSnippetGraphs.put(keyString, snippet);
snippetParameterInfos.put(keyString, new SnippetParameterInfo(method));
keyToMethod.put(keyString, key);
}
}
@ -450,26 +497,22 @@ public class SymbolicSnippetEncoder {
}
encoder.finishPrepare();
byte[] snippetEncoding;
Object[] snippetObjects;
NodeClass<?>[] snippetNodeClasses;
EconomicMap<String, Integer> snippetStartOffsets;
snippetStartOffsets = EconomicMap.create();
EconomicMap<String, EncodedSnippets.GraphData> graphDatas = EconomicMap.create();
MapCursor<String, StructuredGraph> cursor = preparedSnippetGraphs.getEntries();
while (cursor.advance()) {
snippetStartOffsets.put(cursor.getKey(), encoder.encode(cursor.getValue()));
EncodedSnippets.GraphData data = new EncodedSnippets.GraphData(encoder.encode(cursor.getValue()), originalMethods.get(cursor.getKey()), snippetParameterInfos.get(cursor.getKey()));
graphDatas.put(cursor.getKey(), data);
}
snippetEncoding = encoder.getEncoding();
snippetObjects = encoder.getObjects();
snippetNodeClasses = encoder.getNodeClasses();
byte[] snippetEncoding = encoder.getEncoding();
Object[] snippetObjects = encoder.getObjects();
for (int i = 0; i < snippetObjects.length; i++) {
Object o = filterSnippetObject(snippetObjects[i]);
debug.log("snippetObjects[%d] = %s -> %s", i, o != null ? o.getClass().getSimpleName() : null, o);
snippetObjects[i] = o;
}
debug.log("Encoded %d snippet preparedSnippetGraphs using %d bytes with %d objects", snippetStartOffsets.size(), snippetEncoding.length, snippetObjects.length);
return new EncodedSnippets(snippetEncoding, snippetObjects, snippetNodeClasses, snippetStartOffsets, originalMethods, snippetParameterInfos);
debug.log("Encoded %d snippet preparedSnippetGraphs using %d bytes with %d objects", graphDatas.size(), snippetEncoding.length, snippetObjects.length);
return new EncodedSnippets(snippetEncoding, snippetObjects, encoder.getNodeClasses(), graphDatas);
}
/**
@ -594,7 +637,8 @@ public class SymbolicSnippetEncoder {
// Filter these out for now. These can't easily be handled because these positions
// description snippet methods which might not be available in the runtime.
return null;
} else if (o instanceof HotSpotForeignCallsProvider || o instanceof GraalHotSpotVMConfig) {
} else if (o instanceof HotSpotForeignCallsProvider || o instanceof GraalHotSpotVMConfig || o instanceof HotSpotWordTypes || o instanceof TargetDescription ||
o instanceof SnippetReflectionProvider) {
return new GraalCapability(o.getClass());
} else if (o instanceof Stamp) {
SymbolicJVMCIReference<?> ref = ((Stamp) o).makeSymbolic();
@ -731,11 +775,11 @@ public class SymbolicSnippetEncoder {
* as the parser for these snippets.
*/
class HotSpotSnippetReplacementsImpl extends HotSpotReplacementsImpl {
HotSpotSnippetReplacementsImpl(HotSpotReplacementsImpl replacements, Providers providers) {
HotSpotSnippetReplacementsImpl(HotSpotReplacementsImpl replacements, HotSpotProviders providers) {
super(replacements, providers);
}
HotSpotSnippetReplacementsImpl(Providers providers, SnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider, TargetDescription target) {
HotSpotSnippetReplacementsImpl(HotSpotProviders providers, SnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider, TargetDescription target) {
super(providers, snippetReflection, bytecodeProvider, target);
}
@ -764,7 +808,7 @@ public class SymbolicSnippetEncoder {
}
class HotSpotSnippetGraphBuilderPhase extends GraphBuilderPhase.Instance {
HotSpotSnippetGraphBuilderPhase(Providers theProviders, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts, IntrinsicContext initialIntrinsicContext) {
HotSpotSnippetGraphBuilderPhase(CoreProviders theProviders, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts, IntrinsicContext initialIntrinsicContext) {
super(theProviders, graphBuilderConfig, optimisticOpts, initialIntrinsicContext);
}
@ -787,6 +831,11 @@ public class SymbolicSnippetEncoder {
return plugin.isGeneratedFromFoldOrNodeIntrinsic();
}
@Override
public boolean shouldDeferPlugin(GeneratedInvocationPlugin plugin) {
return plugin.isGeneratedFromFoldOrNodeIntrinsic();
}
@Override
protected boolean canInlinePartialIntrinsicExit() {
return false;
@ -797,10 +846,7 @@ public class SymbolicSnippetEncoder {
if (intrinsicContext != null && intrinsicContext.isCallToOriginal(targetMethod)) {
return false;
}
if (targetMethod.getAnnotation(Fold.class) != null) {
// Always defer Fold until decode time but NodeIntrinsics may fold if they are able.
return false;
}
InvocationPlugin plugin = graphBuilderConfig.getPlugins().getInvocationPlugins().lookupInvocation(targetMethod);
if (plugin != null && conditionalPlugins.contains(plugin)) {
// Because supporting arbitrary plugins in the context of encoded graphs is complex

View File

@ -26,6 +26,7 @@ package org.graalvm.compiler.hotspot.meta;
import static jdk.vm.ci.services.Services.IS_IN_NATIVE_IMAGE;
import static org.graalvm.compiler.core.common.GraalOptions.AlwaysInlineVTableStubs;
import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
import static org.graalvm.compiler.core.common.GraalOptions.InlineVTableStubs;
import static org.graalvm.compiler.core.common.GraalOptions.OmitHotExceptionStacktrace;
import static org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProviderImpl.OSR_MIGRATION_END;
@ -229,7 +230,7 @@ public abstract class DefaultHotSpotLoweringProvider extends DefaultJavaLowering
allocationSnippets = new HotSpotAllocationSnippets.Templates(options, factories, runtime, providers, target, config);
monitorSnippets = new MonitorSnippets.Templates(options, factories, runtime, providers, target, config.useFastLocking);
g1WriteBarrierSnippets = new HotSpotG1WriteBarrierSnippets.Templates(options, factories, runtime, providers, target, config);
serialWriteBarrierSnippets = new HotSpotSerialWriteBarrierSnippets.Templates(options, factories, runtime, providers, target, config);
serialWriteBarrierSnippets = new HotSpotSerialWriteBarrierSnippets.Templates(options, factories, runtime, providers, target);
exceptionObjectSnippets = new LoadExceptionObjectSnippets.Templates(options, factories, providers, target);
assertionSnippets = new AssertionSnippets.Templates(options, factories, providers, target);
arraycopySnippets = new ArrayCopySnippets.Templates(new HotSpotArraycopySnippets(), options, factories, runtime, providers, providers.getSnippetReflection(), target);
@ -238,12 +239,12 @@ public abstract class DefaultHotSpotLoweringProvider extends DefaultJavaLowering
resolveConstantSnippets = new ResolveConstantSnippets.Templates(options, factories, providers, target);
objectCloneSnippets = new ObjectCloneSnippets.Templates(options, factories, providers, target);
foreignCallSnippets = new ForeignCallSnippets.Templates(options, factories, providers, target);
if (JavaVersionUtil.JAVA_SPEC >= 11) {
objectSnippets = new ObjectSnippets.Templates(options, factories, providers, target);
}
unsafeSnippets = new UnsafeSnippets.Templates(options, factories, providers, target);
if (JavaVersionUtil.JAVA_SPEC <= 8) {
if (JavaVersionUtil.JAVA_SPEC >= 11 && GeneratePIC.getValue(options)) {
// AOT only introduced in JDK 9
profileSnippets = null;
} else {
profileSnippets = new ProfileSnippets.Templates(options, factories, providers, target);
}
}
@ -419,6 +420,9 @@ public abstract class DefaultHotSpotLoweringProvider extends DefaultJavaLowering
} else if (n instanceof KlassBeingInitializedCheckNode) {
allocationSnippets.lower((KlassBeingInitializedCheckNode) n, tool);
} else if (n instanceof FastNotifyNode) {
if (JavaVersionUtil.JAVA_SPEC < 11) {
throw GraalError.shouldNotReachHere("FastNotify is not support prior to 11");
}
if (graph.getGuardsStage() == GuardsStage.AFTER_FSA) {
objectSnippets.lower(n, tool);
}

View File

@ -179,7 +179,9 @@ public abstract class HotSpotForeignCallsProviderImpl implements HotSpotForeignC
HotSpotForeignCallDescriptor descriptor,
long address,
boolean prependThread) {
if (address != 0) {
if (address == 0) {
throw new IllegalArgumentException("Can't link foreign call with zero address");
}
ForeignCallStub stub = new ForeignCallStub(options, jvmciRuntime, providers, address, descriptor, prependThread);
HotSpotForeignCallLinkage linkage = stub.getLinkage();
HotSpotForeignCallLinkage targetLinkage = stub.getTargetLinkage();
@ -187,7 +189,6 @@ public abstract class HotSpotForeignCallsProviderImpl implements HotSpotForeignC
register(linkage);
register(targetLinkage);
}
}
public static final boolean PREPEND_THREAD = true;
public static final boolean DONT_PREPEND_THREAD = !PREPEND_THREAD;

View File

@ -84,13 +84,13 @@ import org.graalvm.compiler.nodes.calc.IntegerConvertNode;
import org.graalvm.compiler.nodes.calc.LeftShiftNode;
import org.graalvm.compiler.nodes.extended.ForeignCallNode;
import org.graalvm.compiler.nodes.graphbuilderconf.ForeignCallPlugin;
import org.graalvm.compiler.nodes.graphbuilderconf.GeneratedPluginFactory;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin;
import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin.Receiver;
import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins;
import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Registration;
import org.graalvm.compiler.nodes.graphbuilderconf.NodeIntrinsicPluginFactory;
import org.graalvm.compiler.nodes.java.DynamicNewInstanceNode;
import org.graalvm.compiler.nodes.memory.OnHeapMemoryAccess.BarrierType;
import org.graalvm.compiler.nodes.memory.ReadNode;
@ -152,8 +152,8 @@ public class HotSpotGraphBuilderPlugins {
InvocationPlugins invocationPlugins = new HotSpotInvocationPlugins(graalRuntime, config, compilerConfiguration);
Plugins plugins = new Plugins(invocationPlugins);
NodeIntrinsificationProvider nodeIntrinsificationProvider = new NodeIntrinsificationProvider(metaAccess, snippetReflection, foreignCalls, wordTypes, target);
if (!IS_IN_NATIVE_IMAGE) {
// In libgraal all word related operations have been fully processed so this is unneeded
HotSpotWordOperationPlugin wordOperationPlugin = new HotSpotWordOperationPlugin(snippetReflection, wordTypes);
HotSpotNodePlugin nodePlugin = new HotSpotNodePlugin(wordOperationPlugin, config, wordTypes);
@ -161,7 +161,7 @@ public class HotSpotGraphBuilderPlugins {
plugins.appendNodePlugin(nodePlugin);
}
if (!GeneratePIC.getValue(options)) {
plugins.appendNodePlugin(new MethodHandlePlugin(constantReflection.getMethodHandleAccess(), true));
plugins.appendNodePlugin(new MethodHandlePlugin(constantReflection.getMethodHandleAccess(), !config.supportsMethodHandleDeoptimizationEntry()));
}
plugins.appendInlineInvokePlugin(replacements);
if (InlineDuringParsing.getValue(options)) {
@ -205,12 +205,24 @@ public class HotSpotGraphBuilderPlugins {
registerArrayPlugins(invocationPlugins, replacements);
registerStringPlugins(invocationPlugins, replacements);
registerArraysSupportPlugins(invocationPlugins, config, replacements);
for (NodeIntrinsicPluginFactory factory : GraalServices.load(NodeIntrinsicPluginFactory.class)) {
factory.registerPlugins(invocationPlugins, nodeIntrinsificationProvider);
}
}
});
if (!IS_IN_NATIVE_IMAGE) {
// In libgraal all NodeIntrinsics been converted into special nodes so the plugins
// aren't needed.
NodeIntrinsificationProvider nodeIntrinsificationProvider = new NodeIntrinsificationProvider(metaAccess, snippetReflection, foreignCalls, wordTypes, target);
invocationPlugins.defer(new Runnable() {
@Override
public void run() {
for (GeneratedPluginFactory factory : GraalServices.load(GeneratedPluginFactory.class)) {
factory.registerPlugins(invocationPlugins, nodeIntrinsificationProvider);
}
}
});
}
return plugins;
}

View File

@ -128,6 +128,7 @@ import org.graalvm.compiler.nodes.NamedLocationIdentity;
import org.graalvm.compiler.nodes.extended.BytecodeExceptionNode.BytecodeExceptionKind;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.replacements.arraycopy.ArrayCopyForeignCalls;
import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
import org.graalvm.compiler.word.Word;
import org.graalvm.compiler.word.WordTypes;
import jdk.internal.vm.compiler.word.LocationIdentity;
@ -361,8 +362,12 @@ public abstract class HotSpotHostForeignCallsProvider extends HotSpotForeignCall
linkForeignCall(options, providers, createDescriptor(REGISTER_FINALIZER, SAFEPOINT, NOT_REEXECUTABLE, any()), c.registerFinalizerAddress, PREPEND_THREAD);
linkForeignCall(options, providers, MONITORENTER, c.monitorenterAddress, PREPEND_THREAD);
linkForeignCall(options, providers, MONITOREXIT, c.monitorexitAddress, PREPEND_THREAD);
if (JavaVersionUtil.JAVA_SPEC >= 11) {
linkForeignCall(options, providers, NOTIFY, c.notifyAddress, PREPEND_THREAD);
linkForeignCall(options, providers, NOTIFY_ALL, c.notifyAllAddress, PREPEND_THREAD);
} else {
assert c.notifyAddress == 0 : "unexpected value";
}
linkForeignCall(options, providers, LOG_PRINTF, c.logPrintfAddress, PREPEND_THREAD);
linkForeignCall(options, providers, LOG_OBJECT, c.logObjectAddress, PREPEND_THREAD);
linkForeignCall(options, providers, LOG_PRIMITIVE, c.logPrimitiveAddress, PREPEND_THREAD);

View File

@ -26,14 +26,19 @@ package org.graalvm.compiler.hotspot.meta;
import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
import org.graalvm.compiler.core.common.spi.ConstantFieldProvider;
import org.graalvm.compiler.core.common.spi.ForeignCallsProvider;
import org.graalvm.compiler.core.common.spi.MetaAccessExtensionProvider;
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
import org.graalvm.compiler.hotspot.word.HotSpotWordTypes;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
import org.graalvm.compiler.nodes.spi.LoweringProvider;
import org.graalvm.compiler.nodes.spi.PlatformConfigurationProvider;
import org.graalvm.compiler.nodes.spi.Replacements;
import org.graalvm.compiler.nodes.spi.StampProvider;
import org.graalvm.compiler.phases.tiers.SuitesProvider;
import org.graalvm.compiler.phases.util.Providers;
import jdk.vm.ci.code.CodeCacheProvider;
import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider;
import jdk.vm.ci.meta.ConstantReflectionProvider;
import jdk.vm.ci.meta.MetaAccessProvider;
@ -46,20 +51,40 @@ public class HotSpotProviders extends Providers {
private final SuitesProvider suites;
private final HotSpotRegistersProvider registers;
private final SnippetReflectionProvider snippetReflection;
private final HotSpotWordTypes wordTypes;
private final Plugins graphBuilderPlugins;
private final GraalHotSpotVMConfig config;
public HotSpotProviders(MetaAccessProvider metaAccess, HotSpotCodeCacheProvider codeCache, ConstantReflectionProvider constantReflection, ConstantFieldProvider constantField,
HotSpotForeignCallsProvider foreignCalls, LoweringProvider lowerer, Replacements replacements, SuitesProvider suites, HotSpotRegistersProvider registers,
SnippetReflectionProvider snippetReflection, HotSpotWordTypes wordTypes, Plugins graphBuilderPlugins, HotSpotPlatformConfigurationProvider platformConfigurationProvider,
MetaAccessExtensionProvider metaAccessExtensionProvider) {
super(metaAccess, codeCache, constantReflection, constantField, foreignCalls, lowerer, replacements, new HotSpotStampProvider(), platformConfigurationProvider, metaAccessExtensionProvider);
public HotSpotProviders(MetaAccessProvider metaAccess,
HotSpotCodeCacheProvider codeCache,
ConstantReflectionProvider constantReflection,
ConstantFieldProvider constantField,
HotSpotHostForeignCallsProvider foreignCalls,
LoweringProvider lowerer,
Replacements replacements,
SuitesProvider suites,
HotSpotRegistersProvider registers,
SnippetReflectionProvider snippetReflection,
HotSpotWordTypes wordTypes,
Plugins graphBuilderPlugins,
PlatformConfigurationProvider platformConfigurationProvider,
MetaAccessExtensionProvider metaAccessExtensionProvider,
GraalHotSpotVMConfig config) {
super(metaAccess, codeCache, constantReflection, constantField, foreignCalls, lowerer, replacements, new HotSpotStampProvider(), platformConfigurationProvider, metaAccessExtensionProvider,
snippetReflection, wordTypes);
this.suites = suites;
this.registers = registers;
this.snippetReflection = snippetReflection;
this.wordTypes = wordTypes;
this.graphBuilderPlugins = graphBuilderPlugins;
this.config = config;
}
public HotSpotProviders(MetaAccessProvider metaAccess, CodeCacheProvider codeCache, ConstantReflectionProvider constantReflection, ConstantFieldProvider constantField,
ForeignCallsProvider foreignCalls, LoweringProvider lowerer, Replacements replacements, StampProvider stampProvider, PlatformConfigurationProvider platformConfigurationProvider,
MetaAccessExtensionProvider metaAccessExtensionProvider) {
super(metaAccess, codeCache, constantReflection, constantField, foreignCalls, lowerer, replacements, stampProvider, platformConfigurationProvider, metaAccessExtensionProvider, null, null);
this.suites = null;
this.registers = null;
this.graphBuilderPlugins = null;
this.config = null;
}
@Override
@ -68,8 +93,8 @@ public class HotSpotProviders extends Providers {
}
@Override
public HotSpotForeignCallsProvider getForeignCalls() {
return (HotSpotForeignCallsProvider) super.getForeignCalls();
public HotSpotHostForeignCallsProvider getForeignCalls() {
return (HotSpotHostForeignCallsProvider) super.getForeignCalls();
}
public SuitesProvider getSuites() {
@ -80,47 +105,46 @@ public class HotSpotProviders extends Providers {
return registers;
}
public SnippetReflectionProvider getSnippetReflection() {
return snippetReflection;
}
public Plugins getGraphBuilderPlugins() {
return graphBuilderPlugins;
}
@Override
public HotSpotWordTypes getWordTypes() {
return wordTypes;
return (HotSpotWordTypes) super.getWordTypes();
}
public GraalHotSpotVMConfig getConfig() {
return config;
}
@Override
public HotSpotPlatformConfigurationProvider getPlatformConfigurationProvider() {
return (HotSpotPlatformConfigurationProvider) super.getPlatformConfigurationProvider();
return (HotSpotPlatformConfigurationProvider) platformConfigurationProvider;
}
@Override
public Providers copyWith(ConstantReflectionProvider substitution) {
assert this.getClass() == HotSpotProviders.class : "must override in " + getClass();
public HotSpotProviders copyWith(ConstantReflectionProvider substitution) {
return new HotSpotProviders(getMetaAccess(), getCodeCache(), substitution, getConstantFieldProvider(), getForeignCalls(), getLowerer(), getReplacements(), getSuites(),
getRegisters(), getSnippetReflection(), getWordTypes(), getGraphBuilderPlugins(), getPlatformConfigurationProvider(), getMetaAccessExtensionProvider());
getRegisters(), getSnippetReflection(), getWordTypes(), getGraphBuilderPlugins(), getPlatformConfigurationProvider(), getMetaAccessExtensionProvider(), config);
}
@Override
public Providers copyWith(ConstantFieldProvider substitution) {
assert this.getClass() == HotSpotProviders.class : "must override in " + getClass();
return new HotSpotProviders(getMetaAccess(), getCodeCache(), getConstantReflection(), substitution, getForeignCalls(), getLowerer(), getReplacements(), getSuites(),
getRegisters(), getSnippetReflection(), getWordTypes(), getGraphBuilderPlugins(), getPlatformConfigurationProvider(), getMetaAccessExtensionProvider());
public HotSpotProviders copyWith(ConstantFieldProvider substitution) {
return new HotSpotProviders(getMetaAccess(), getCodeCache(), getConstantReflection(), substitution, getForeignCalls(), getLowerer(), getReplacements(),
getSuites(),
getRegisters(), getSnippetReflection(), getWordTypes(), getGraphBuilderPlugins(), getPlatformConfigurationProvider(), getMetaAccessExtensionProvider(), config);
}
@Override
public Providers copyWith(Replacements substitution) {
assert this.getClass() == HotSpotProviders.class : "must override in " + getClass();
return new HotSpotProviders(getMetaAccess(), getCodeCache(), getConstantReflection(), getConstantFieldProvider(), getForeignCalls(), getLowerer(), substitution, getSuites(),
getRegisters(), getSnippetReflection(), getWordTypes(), getGraphBuilderPlugins(), getPlatformConfigurationProvider(), getMetaAccessExtensionProvider());
public HotSpotProviders copyWith(Replacements substitution) {
return new HotSpotProviders(getMetaAccess(), getCodeCache(), getConstantReflection(), getConstantFieldProvider(), getForeignCalls(), getLowerer(), substitution,
getSuites(), getRegisters(), getSnippetReflection(), getWordTypes(), getGraphBuilderPlugins(), getPlatformConfigurationProvider(), getMetaAccessExtensionProvider(), config);
}
public Providers copyWith(Plugins substitution) {
assert this.getClass() == HotSpotProviders.class : "must override in " + getClass();
return new HotSpotProviders(getMetaAccess(), getCodeCache(), getConstantReflection(), getConstantFieldProvider(), getForeignCalls(), getLowerer(), getReplacements(), getSuites(),
getRegisters(), getSnippetReflection(), getWordTypes(), substitution, getPlatformConfigurationProvider(), getMetaAccessExtensionProvider());
public HotSpotProviders copyWith(Plugins substitution) {
return new HotSpotProviders(getMetaAccess(), getCodeCache(), getConstantReflection(), getConstantFieldProvider(), getForeignCalls(), getLowerer(), getReplacements(),
getSuites(), getRegisters(), getSnippetReflection(), getWordTypes(), substitution, getPlatformConfigurationProvider(), getMetaAccessExtensionProvider(), config);
}
}

View File

@ -32,13 +32,13 @@ import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.graph.Node.NodeIntrinsicFactory;
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.graph.spi.Canonicalizable;
import org.graalvm.compiler.graph.spi.CanonicalizerTool;
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
import org.graalvm.compiler.hotspot.HotSpotLIRGenerator;
import org.graalvm.compiler.hotspot.HotSpotMarkId;
import org.graalvm.compiler.hotspot.HotSpotReplacementsImpl;
import org.graalvm.compiler.nodeinfo.NodeInfo;
import org.graalvm.compiler.nodes.ConstantNode;
import org.graalvm.compiler.nodes.calc.FloatingNode;
@ -47,13 +47,13 @@ import org.graalvm.compiler.nodes.spi.LIRLowerable;
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.meta.Value;
/**
* Represents {@link GraalHotSpotVMConfig} values that may change after compilation.
*/
@NodeInfo(cycles = CYCLES_1, size = SIZE_1)
@NodeIntrinsicFactory
public class GraalHotSpotVMConfigNode extends FloatingNode implements LIRLowerable, Canonicalizable {
public static final NodeClass<GraalHotSpotVMConfigNode> TYPE = NodeClass.create(GraalHotSpotVMConfigNode.class);
@ -109,11 +109,8 @@ public class GraalHotSpotVMConfigNode extends FloatingNode implements LIRLowerab
return loadIntConfigValue(HotSpotMarkId.LOG_OF_HEAP_REGION_GRAIN_BYTES);
}
@SuppressWarnings("unused")
public static boolean intrinsify(GraphBuilderContext b, ResolvedJavaMethod method, @InjectedNodeParameter Stamp returnStamp, @InjectedNodeParameter GraalHotSpotVMConfig config,
HotSpotMarkId mark) {
HotSpotReplacementsImpl replacements = (HotSpotReplacementsImpl) b.getReplacements();
if (replacements.isEncodingSnippets()) {
public static boolean intrinsify(GraphBuilderContext b, @InjectedNodeParameter Stamp returnStamp, @InjectedNodeParameter GraalHotSpotVMConfig config, HotSpotMarkId mark) {
if (b.getReplacements().isEncodingSnippets()) {
// This plugin must be deferred so that these constants aren't embedded in libgraal
return false;
}

View File

@ -30,6 +30,7 @@ import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1;
import org.graalvm.compiler.core.common.calc.CanonicalCondition;
import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.graph.Node.NodeIntrinsicFactory;
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.graph.spi.Canonicalizable;
import org.graalvm.compiler.graph.spi.CanonicalizerTool;
@ -56,7 +57,6 @@ import jdk.vm.ci.meta.ConstantReflectionProvider;
import jdk.vm.ci.meta.JavaConstant;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.MetaAccessProvider;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.meta.ResolvedJavaType;
/**
@ -66,6 +66,7 @@ import jdk.vm.ci.meta.ResolvedJavaType;
* {@link ReadNode#canonicalizeRead(ValueNode, AddressNode, LocationIdentity, CanonicalizerTool)}.
*/
@NodeInfo(cycles = CYCLES_1, size = SIZE_1)
@NodeIntrinsicFactory
public final class ClassGetHubNode extends FloatingNode implements Lowerable, Canonicalizable, ConvertNode {
public static final NodeClass<ClassGetHubNode> TYPE = NodeClass.create(ClassGetHubNode.class);
@Input protected ValueNode clazz;
@ -79,8 +80,7 @@ public final class ClassGetHubNode extends FloatingNode implements Lowerable, Ca
return canonical(null, metaAccess, constantReflection, allUsagesAvailable, KlassPointerStamp.klass(), clazz);
}
@SuppressWarnings("unused")
public static boolean intrinsify(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode clazz) {
public static boolean intrinsify(GraphBuilderContext b, ValueNode clazz) {
ValueNode clazzValue = create(clazz, b.getMetaAccess(), b.getConstantReflection(), false);
b.push(JavaKind.Object, b.append(clazzValue));
return true;

View File

@ -151,7 +151,7 @@ public class HotSpotAllocationSnippets extends AllocationSnippets {
@ConstantParameter long size,
@ConstantParameter boolean fillContents,
@ConstantParameter boolean emitMemoryBarrier,
@ConstantParameter AllocationProfilingData profilingData) {
@ConstantParameter HotSpotAllocationProfilingData profilingData) {
Object result = allocateInstanceImpl(hub.asWord(), prototypeMarkWord, WordFactory.unsigned(size), fillContents, emitMemoryBarrier, true, profilingData);
return piCastToSnippetReplaceeStamp(result);
}
@ -166,7 +166,7 @@ public class HotSpotAllocationSnippets extends AllocationSnippets {
@ConstantParameter boolean emitMemoryBarrier,
@ConstantParameter boolean maybeUnroll,
@ConstantParameter boolean supportsBulkZeroing,
@ConstantParameter AllocationProfilingData profilingData) {
@ConstantParameter HotSpotAllocationProfilingData profilingData) {
Object result = allocateArrayImpl(hub.asWord(), prototypeMarkWord, length, headerSize, log2ElementSize, fillContents, headerSize, emitMemoryBarrier, maybeUnroll, supportsBulkZeroing,
profilingData);
return piArrayCastToSnippetReplaceeStamp(result, length);
@ -178,7 +178,7 @@ public class HotSpotAllocationSnippets extends AllocationSnippets {
@ConstantParameter long size,
@ConstantParameter boolean fillContents,
@ConstantParameter boolean emitMemoryBarrier,
@ConstantParameter AllocationProfilingData profilingData) {
@ConstantParameter HotSpotAllocationProfilingData profilingData) {
// Klass must be initialized by the time the first instance is allocated, therefore we can
// just load it from the corresponding cell and avoid the resolution check. We have to use a
// fixed load though, to prevent it from floating above the initialization.
@ -192,7 +192,7 @@ public class HotSpotAllocationSnippets extends AllocationSnippets {
Class<?> classClass,
@ConstantParameter boolean fillContents,
@ConstantParameter boolean emitMemoryBarrier,
@ConstantParameter AllocationProfilingData profilingData) {
@ConstantParameter HotSpotAllocationProfilingData profilingData) {
if (probability(DEOPT_PROBABILITY, type == null)) {
DeoptimizeNode.deopt(None, RuntimeConstraint);
}
@ -240,7 +240,7 @@ public class HotSpotAllocationSnippets extends AllocationSnippets {
@ConstantParameter boolean emitMemoryBarrier,
@ConstantParameter boolean maybeUnroll,
@ConstantParameter boolean supportsBulkZeroing,
@ConstantParameter AllocationProfilingData profilingData) {
@ConstantParameter HotSpotAllocationProfilingData profilingData) {
// Primitive array types are eagerly pre-resolved. We can use a floating load.
KlassPointer picHub = LoadConstantIndirectlyNode.loadKlass(hub);
return allocateArrayImpl(picHub.asWord(), prototypeMarkWord, length, headerSize, log2ElementSize, fillContents, headerSize, emitMemoryBarrier, maybeUnroll, supportsBulkZeroing, profilingData);
@ -256,7 +256,7 @@ public class HotSpotAllocationSnippets extends AllocationSnippets {
@ConstantParameter boolean emitMemoryBarrier,
@ConstantParameter boolean maybeUnroll,
@ConstantParameter boolean supportsBulkZeroing,
@ConstantParameter AllocationProfilingData profilingData) {
@ConstantParameter HotSpotAllocationProfilingData profilingData) {
// Array type would be resolved by dominating resolution.
KlassPointer picHub = LoadConstantIndirectlyFixedNode.loadKlass(hub);
return allocateArrayImpl(picHub.asWord(), prototypeMarkWord, length, headerSize, log2ElementSize, fillContents, headerSize, emitMemoryBarrier, maybeUnroll, supportsBulkZeroing, profilingData);
@ -272,7 +272,7 @@ public class HotSpotAllocationSnippets extends AllocationSnippets {
@ConstantParameter JavaKind knownElementKind,
@ConstantParameter int knownLayoutHelper,
@ConstantParameter boolean supportsBulkZeroing,
@ConstantParameter AllocationProfilingData profilingData) {
@ConstantParameter HotSpotAllocationProfilingData profilingData) {
/*
* We only need the dynamic check for void when we have no static information from
* knownElementKind.
@ -637,7 +637,7 @@ public class HotSpotAllocationSnippets extends AllocationSnippets {
threadBeingInitializedCheck = snippet(HotSpotAllocationSnippets.class, "threadBeingInitializedCheck", null, receiver);
}
private AllocationProfilingData getProfilingData(OptionValues localOptions, String path, ResolvedJavaType type) {
private HotSpotAllocationProfilingData getProfilingData(OptionValues localOptions, String path, ResolvedJavaType type) {
if (ProfileAllocations.getValue(localOptions)) {
// Create one object per snippet instantiation - this kills the snippet caching as
// we need to add the object as a constant to the snippet.

View File

@ -55,6 +55,7 @@ import org.graalvm.compiler.replacements.SnippetTemplate.AbstractTemplates;
import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo;
import org.graalvm.compiler.replacements.gc.G1WriteBarrierSnippets;
import org.graalvm.compiler.word.Word;
import jdk.internal.vm.compiler.word.Pointer;
import jdk.internal.vm.compiler.word.WordFactory;
import jdk.vm.ci.code.Register;
@ -68,11 +69,9 @@ public final class HotSpotG1WriteBarrierSnippets extends G1WriteBarrierSnippets
public static final HotSpotForeignCallDescriptor VALIDATE_OBJECT = new HotSpotForeignCallDescriptor(LEAF_NO_VZERO, REEXECUTABLE, NO_LOCATIONS, "validate_object", boolean.class, Word.class,
Word.class);
private final GraalHotSpotVMConfig config;
private final Register threadRegister;
public HotSpotG1WriteBarrierSnippets(GraalHotSpotVMConfig config, HotSpotRegistersProvider registers) {
this.config = config;
public HotSpotG1WriteBarrierSnippets(HotSpotRegistersProvider registers) {
this.threadRegister = registers.getThreadRegister();
}
@ -127,13 +126,10 @@ public final class HotSpotG1WriteBarrierSnippets extends G1WriteBarrierSnippets
}
@Override
protected Word cardTableAddress() {
return WordFactory.unsigned(GraalHotSpotVMConfigNode.cardTableAddress());
}
@Override
protected int cardTableShift() {
return HotSpotReplacementsUtil.cardTableShift(INJECTED_VMCONFIG);
protected Word cardTableAddress(Pointer oop) {
Word cardTable = WordFactory.unsigned(GraalHotSpotVMConfigNode.cardTableAddress());
int cardTableShift = HotSpotReplacementsUtil.cardTableShift(INJECTED_VMCONFIG);
return cardTable.add(oop.unsignedShiftRight(cardTableShift));
}
@Override
@ -158,7 +154,7 @@ public final class HotSpotG1WriteBarrierSnippets extends G1WriteBarrierSnippets
@Override
protected boolean verifyBarrier() {
return ReplacementsUtil.REPLACEMENTS_ASSERTIONS_ENABLED || config.verifyBeforeGC || config.verifyAfterGC;
return ReplacementsUtil.REPLACEMENTS_ASSERTIONS_ENABLED || HotSpotReplacementsUtil.verifyBeforeOrAfterGC(INJECTED_VMCONFIG);
}
@Override
@ -204,7 +200,7 @@ public final class HotSpotG1WriteBarrierSnippets extends G1WriteBarrierSnippets
super(options, factories, providers, providers.getSnippetReflection(), target);
this.lowerer = new HotspotG1WriteBarrierLowerer(config, factory);
HotSpotG1WriteBarrierSnippets receiver = new HotSpotG1WriteBarrierSnippets(config, providers.getRegisters());
HotSpotG1WriteBarrierSnippets receiver = new HotSpotG1WriteBarrierSnippets(providers.getRegisters());
g1PreWriteBarrier = snippet(G1WriteBarrierSnippets.class, "g1PreWriteBarrier", null, receiver, GC_INDEX_LOCATION, GC_LOG_LOCATION, SATB_QUEUE_MARKING_LOCATION, SATB_QUEUE_INDEX_LOCATION,
SATB_QUEUE_BUFFER_LOCATION);
g1ReferentReadBarrier = snippet(G1WriteBarrierSnippets.class, "g1ReferentReadBarrier", null, receiver, GC_INDEX_LOCATION, GC_LOG_LOCATION, SATB_QUEUE_MARKING_LOCATION,

View File

@ -605,6 +605,11 @@ public class HotSpotReplacementsUtil {
return WordFactory.unsigned(ComputeObjectAddressNode.get(a, ReplacementsUtil.getArrayBaseOffset(INJECTED_METAACCESS, JavaKind.Int)));
}
@Fold
public static boolean verifyBeforeOrAfterGC(@InjectedParameter GraalHotSpotVMConfig config) {
return config.verifyBeforeGC || config.verifyAfterGC;
}
/**
* Idiom for making {@link GraalHotSpotVMConfig} a constant.
*/

View File

@ -27,7 +27,6 @@ package org.graalvm.compiler.hotspot.replacements;
import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG;
import org.graalvm.compiler.debug.DebugHandlersFactory;
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
import org.graalvm.compiler.hotspot.nodes.GraalHotSpotVMConfigNode;
import org.graalvm.compiler.nodes.gc.SerialArrayRangeWriteBarrier;
@ -45,10 +44,8 @@ import jdk.internal.vm.compiler.word.WordFactory;
import jdk.vm.ci.code.TargetDescription;
public class HotSpotSerialWriteBarrierSnippets extends SerialWriteBarrierSnippets {
private final GraalHotSpotVMConfig config;
public HotSpotSerialWriteBarrierSnippets(GraalHotSpotVMConfig config) {
this.config = config;
public HotSpotSerialWriteBarrierSnippets() {
}
@Override
@ -63,12 +60,12 @@ public class HotSpotSerialWriteBarrierSnippets extends SerialWriteBarrierSnippet
@Override
public boolean verifyBarrier() {
return ReplacementsUtil.REPLACEMENTS_ASSERTIONS_ENABLED || config.verifyBeforeGC || config.verifyAfterGC;
return ReplacementsUtil.REPLACEMENTS_ASSERTIONS_ENABLED || HotSpotReplacementsUtil.verifyBeforeOrAfterGC(INJECTED_VMCONFIG);
}
@Override
protected byte dirtyCardValue() {
return config.dirtyCardValue;
return HotSpotReplacementsUtil.dirtyCardValue(INJECTED_VMCONFIG);
}
public static class Templates extends AbstractTemplates {
@ -78,11 +75,11 @@ public class HotSpotSerialWriteBarrierSnippets extends SerialWriteBarrierSnippet
private final SerialWriteBarrierLowerer lowerer;
public Templates(OptionValues options, Iterable<DebugHandlersFactory> factories, Group.Factory factory, HotSpotProviders providers, TargetDescription target, GraalHotSpotVMConfig config) {
public Templates(OptionValues options, Iterable<DebugHandlersFactory> factories, Group.Factory factory, HotSpotProviders providers, TargetDescription target) {
super(options, factories, providers, providers.getSnippetReflection(), target);
this.lowerer = new SerialWriteBarrierLowerer(factory);
HotSpotSerialWriteBarrierSnippets receiver = new HotSpotSerialWriteBarrierSnippets(config);
HotSpotSerialWriteBarrierSnippets receiver = new HotSpotSerialWriteBarrierSnippets();
serialImpreciseWriteBarrier = snippet(SerialWriteBarrierSnippets.class, "serialImpreciseWriteBarrier", null, receiver, GC_CARD_LOCATION);
serialPreciseWriteBarrier = snippet(SerialWriteBarrierSnippets.class, "serialPreciseWriteBarrier", null, receiver, GC_CARD_LOCATION);
serialArrayRangeWriteBarrier = snippet(SerialWriteBarrierSnippets.class, "serialArrayRangeWriteBarrier", null, receiver, GC_CARD_LOCATION);

View File

@ -31,6 +31,7 @@ import org.graalvm.compiler.core.common.type.ObjectStamp;
import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.graph.Node.NodeIntrinsicFactory;
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.graph.spi.Canonicalizable;
import org.graalvm.compiler.graph.spi.CanonicalizerTool;
@ -49,7 +50,6 @@ import jdk.vm.ci.meta.Constant;
import jdk.vm.ci.meta.ConstantReflectionProvider;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.MetaAccessProvider;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.meta.ResolvedJavaType;
/**
@ -57,6 +57,7 @@ import jdk.vm.ci.meta.ResolvedJavaType;
* information in {@code klass}.
*/
@NodeInfo(cycles = CYCLES_1, size = SIZE_1)
@NodeIntrinsicFactory
public final class KlassLayoutHelperNode extends FloatingNode implements Canonicalizable, Lowerable {
public static final NodeClass<KlassLayoutHelperNode> TYPE = NodeClass.create(KlassLayoutHelperNode.class);
@ -74,8 +75,7 @@ public final class KlassLayoutHelperNode extends FloatingNode implements Canonic
return canonical(null, config, klass, stamp, constantReflection, metaAccess);
}
@SuppressWarnings("unused")
public static boolean intrinsify(GraphBuilderContext b, ResolvedJavaMethod method, @InjectedNodeParameter GraalHotSpotVMConfig config, ValueNode klass) {
public static boolean intrinsify(GraphBuilderContext b, @InjectedNodeParameter GraalHotSpotVMConfig config, ValueNode klass) {
ValueNode valueNode = create(config, klass, b.getConstantReflection(), b.getMetaAccess());
b.push(JavaKind.Int, b.append(valueNode));
return true;

View File

@ -349,6 +349,7 @@ import org.graalvm.compiler.nodes.MergeNode;
import org.graalvm.compiler.nodes.NodeView;
import org.graalvm.compiler.nodes.ParameterNode;
import org.graalvm.compiler.nodes.PiNode;
import org.graalvm.compiler.nodes.PluginReplacementNode;
import org.graalvm.compiler.nodes.ReturnNode;
import org.graalvm.compiler.nodes.StartNode;
import org.graalvm.compiler.nodes.StateSplit;
@ -396,6 +397,7 @@ import org.graalvm.compiler.nodes.extended.LoadHubNode;
import org.graalvm.compiler.nodes.extended.MembarNode;
import org.graalvm.compiler.nodes.extended.StateSplitProxyNode;
import org.graalvm.compiler.nodes.graphbuilderconf.ClassInitializationPlugin;
import org.graalvm.compiler.nodes.graphbuilderconf.GeneratedInvocationPlugin;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.BytecodeExceptionMode;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
@ -2173,7 +2175,22 @@ public class BytecodeParser implements GraphBuilderContext {
}
}
@SuppressWarnings("try")
@Override
public void replacePlugin(GeneratedInvocationPlugin plugin, ResolvedJavaMethod targetMethod, ValueNode[] args, PluginReplacementNode.ReplacementFunction replacementFunction) {
assert replacementFunction != null;
JavaType returnType = maybeEagerlyResolve(targetMethod.getSignature().getReturnType(method.getDeclaringClass()), targetMethod.getDeclaringClass());
StampPair returnStamp = getReplacements().getGraphBuilderPlugins().getOverridingStamp(this, returnType, false);
if (returnStamp == null) {
returnStamp = StampFactory.forDeclaredType(getAssumptions(), returnType, false);
}
ValueNode node = new PluginReplacementNode(returnStamp.getTrustedStamp(), args, replacementFunction, plugin.getClass().getSimpleName());
if (returnType.getJavaKind() == JavaKind.Void) {
add(node);
} else {
addPush(returnType.getJavaKind(), node);
}
}
protected boolean tryInvocationPlugin(InvokeKind invokeKind, ValueNode[] args, ResolvedJavaMethod targetMethod, JavaKind resultType) {
InvocationPlugin plugin = graphBuilderConfig.getPlugins().getInvocationPlugins().lookupInvocation(targetMethod);
if (plugin != null) {
@ -2183,6 +2200,15 @@ public class BytecodeParser implements GraphBuilderContext {
return false;
}
if (applyInvocationPlugin(invokeKind, args, targetMethod, resultType, plugin)) {
return !plugin.isDecorator();
}
}
return false;
}
@SuppressWarnings("try")
protected boolean applyInvocationPlugin(InvokeKind invokeKind, ValueNode[] args, ResolvedJavaMethod targetMethod, JavaKind resultType, InvocationPlugin plugin) {
InvocationPluginReceiver pluginReceiver = invocationPluginReceiver.init(targetMethod, args);
assert invokeKind.isDirect() : "Cannot apply invocation plugin on an indirect call site.";
@ -2190,12 +2216,11 @@ public class BytecodeParser implements GraphBuilderContext {
try (DebugCloseable context = openNodeContext(targetMethod)) {
if (plugin.execute(this, targetMethod, pluginReceiver, args)) {
assert assertions.check(true);
return !plugin.isDecorator();
return true;
} else {
assert assertions.check(false);
}
}
}
return false;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -32,12 +32,11 @@ import jdk.vm.ci.meta.ResolvedJavaMethod;
/*
*/
public class Math_abs extends UnaryMath {
@SuppressWarnings("serial")
public static class NaN extends Throwable {
}
public static double test(double arg) throws NaN {
public static double testAbsD(double arg) throws NaN {
double v = Math.abs(arg);
if (Double.isNaN(v)) {
// NaN can't be tested against itself
@ -48,43 +47,73 @@ public class Math_abs extends UnaryMath {
@Test
public void run0() throws Throwable {
runTest("test", 5.0d);
runTest("testAbsD", 5.0d);
}
@Test
public void run1() throws Throwable {
runTest("test", -5.0d);
runTest("testAbsD", -5.0d);
}
@Test
public void run2() throws Throwable {
runTest("test", 0.0d);
runTest("testAbsD", 0.0d);
}
@Test
public void run3() throws Throwable {
runTest("test", -0.0d);
runTest("testAbsD", -0.0d);
}
@Test
public void run4() throws Throwable {
runTest("test", java.lang.Double.NEGATIVE_INFINITY);
runTest("testAbsD", java.lang.Double.NEGATIVE_INFINITY);
}
@Test
public void run5() throws Throwable {
runTest("test", java.lang.Double.POSITIVE_INFINITY);
runTest("testAbsD", java.lang.Double.POSITIVE_INFINITY);
}
@Test
public void run6() throws Throwable {
runTest("test", java.lang.Double.NaN);
runTest("testAbsD", java.lang.Double.NaN);
}
@Test
public void run7() {
OptionValues options = getInitialOptions();
ResolvedJavaMethod method = getResolvedJavaMethod("test");
ResolvedJavaMethod method = getResolvedJavaMethod("testAbsD");
testManyValues(options, method);
}
public static int testAbsI(int arg) {
return Math.abs(arg);
}
public static long testAbsL(long arg) {
return Math.abs(arg);
}
@Test
public void run8() {
runTest("testAbsI", Integer.MIN_VALUE);
runTest("testAbsI", -326543323);
runTest("testAbsI", -21325);
runTest("testAbsI", -0);
runTest("testAbsI", 5432);
runTest("testAbsI", 352438548);
runTest("testAbsI", Integer.MAX_VALUE);
}
@Test
public void run9() {
runTest("testAbsL", Long.MIN_VALUE);
runTest("testAbsL", -425423654342L);
runTest("testAbsL", -21543224L);
runTest("testAbsL", -0L);
runTest("testAbsL", 1325488L);
runTest("testAbsL", 313567897765L);
runTest("testAbsL", Long.MAX_VALUE);
}
}

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, Arm Limited and affiliates. All rights reserved.
* Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2020, Arm Limited and affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -42,6 +42,8 @@ import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
*/
public class AArch64BitFieldOp extends AArch64LIRInstruction {
public enum BitFieldOpCode {
SBFX,
SBFIZ,
UBFX,
UBFIZ,
}
@ -68,8 +70,14 @@ public class AArch64BitFieldOp extends AArch64LIRInstruction {
protected void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) {
Register dst = asRegister(result);
Register src = asRegister(input);
final int size = input.getPlatformKind().getSizeInBytes() * Byte.SIZE;
final int size = result.getPlatformKind().getSizeInBytes() * Byte.SIZE;
switch (opcode) {
case SBFX:
masm.sbfm(size, dst, src, lsb, lsb + width - 1);
break;
case SBFIZ:
masm.sbfm(size, dst, src, size - lsb, width - 1);
break;
case UBFX:
masm.ubfm(size, dst, src, lsb, lsb + width - 1);
break;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2009, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -673,9 +673,20 @@ class LinearScanWalker extends IntervalWalker {
splitBeforeUsage(interval, minSplitPos, registerAvailableUntil);
}
void splitAndSpillInterval(Interval interval) {
/**
* Split and spill the given interval. The interval is unconditionally split into a left and
* right part. However, if the {@code mustHaveRegUsePos} of the supplied (selected in the
* caller) register is later than the entire range of the left interval after splitting, we can
* allocate the interval to register {@code reg} without spilling it eagerly.
*
* @param interval the {@linkplain Interval} to split and spill
* @param reg a register selected in the caller most suitable for allocating {@code interval}
* to, only used if the left interval after splitting can be allocated to reg since
* the first {@code mustHaveRegUsePos} of {@code reg} is later
* @param mustHaveRegUsePos the first must have usage of the register
*/
void splitAndSpillInterval(Interval interval, Register reg, int mustHaveRegUsePos) {
assert interval.state == State.Active || interval.state == State.Inactive : "other states not allowed";
int currentPos = currentPosition;
if (interval.state == State.Inactive) {
// the interval is currently inactive, so no spill slot is needed for now.
@ -695,7 +706,40 @@ class LinearScanWalker extends IntervalWalker {
splitBeforeUsage(interval, minSplitPos, maxSplitPos);
assert interval.nextUsage(RegisterPriority.MustHaveRegister, currentPos) == Integer.MAX_VALUE : "the remaining part is spilled to stack and therefore has no register";
if (interval.to() >= mustHaveRegUsePos) {
splitForSpilling(interval);
} else {
/*
* Only need to split'n'spill if the register selected has a usage in the current
* interval's range.
*
* Special case loop phi inputs: if we have a loop phi that has no usage inside the
* loop (and the phi has a usage far away in range) we are tempted to spill the left
* interval at definition of the loop phi, however this can cause move resolution to
* insert spill moves to the stack (phi resolve) inside the body of the loop for
* loop end phi inputs.
*
* In this special scenario we have an interval (loop phi forward end input) that
* has no usage inside the loop just far away from the loop, but the register we
* selected has its first usage outside of the range, so instead of eagerly spilling
* here we use the register and hope it suffices to keep the loop phi in register
* altogether, if not possible we can still spill the register and re-use it
* (hopefully at a better position).
*/
assert reg != null;
boolean needSplit = blockPos[reg.number] <= interval.to();
int splitPos = blockPos[reg.number];
assert splitPos > 0 : "invalid splitPos";
assert needSplit || splitPos > interval.from() : "splitting interval at from";
interval.assignLocation(reg.asValue(interval.kind()));
if (needSplit) {
// register not available for full interval : so split it
splitWhenPartialRegisterAvailable(interval, splitPos);
}
// perform splitting and spilling for all affected intervals
splitAndSpillIntersectingIntervals(reg);
}
}
}
@ -789,11 +833,10 @@ class LinearScanWalker extends IntervalWalker {
void splitAndSpillIntersectingIntervals(Register reg) {
assert reg != null : "no register assigned";
for (int i = 0; i < spillIntervals[reg.number].size(); i++) {
Interval interval = spillIntervals[reg.number].get(i);
removeFromList(interval);
splitAndSpillInterval(interval);
splitAndSpillInterval(interval, null, -1/* unconditionally split and spill */);
}
}
@ -872,8 +915,12 @@ class LinearScanWalker extends IntervalWalker {
throw new OutOfRegistersException("LinearScan: no register found", description);
}
splitAndSpillInterval(interval);
splitAndSpillInterval(interval, reg, regUsePos);
return;
} else {
if (debug.isLogEnabled()) {
debug.log("not able to spill current interval. firstUsage(register): %d, usePos: %d", firstUsage, regUsePos);
}
}
break;
}

View File

@ -189,6 +189,12 @@ public class CompilationResultBuilder {
return !uncompressedNullRegister.equals(Register.None) && JavaConstant.NULL_POINTER.equals(nullConstant);
}
/**
* This flag indicates whether the assembler should emit a separate deoptimization handler for
* method handle invocations.
*/
private boolean needsMHDeoptHandler = false;
public CompilationResultBuilder(CodeCacheProvider codeCache,
ForeignCallsProvider foreignCalls,
FrameMap frameMap,
@ -729,4 +735,12 @@ public class CompilationResultBuilder {
}
return currentCallContext;
}
public void setNeedsMHDeoptHandler() {
this.needsMHDeoptHandler = true;
}
public boolean needsMHDeoptHandler() {
return needsMHDeoptHandler;
}
}

View File

@ -64,7 +64,6 @@ import org.graalvm.compiler.nodes.util.GraphUtil;
import org.graalvm.compiler.phases.BasePhase;
import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase;
import org.graalvm.compiler.phases.common.LazyValue;
import org.graalvm.compiler.phases.util.Providers;
import jdk.vm.ci.meta.Constant;
import jdk.vm.ci.meta.DeoptimizationAction;
@ -83,8 +82,6 @@ import jdk.vm.ci.meta.DeoptimizationAction;
*/
public class ConvertDeoptimizeToGuardPhase extends BasePhase<CoreProviders> {
private static final Providers EMPTY_PROVIDERS = new Providers(null, null, null, null, null, null, null, null, null, null);
@Override
@SuppressWarnings("try")
protected void run(final StructuredGraph graph, CoreProviders context) {
@ -228,7 +225,8 @@ public class ConvertDeoptimizeToGuardPhase extends BasePhase<CoreProviders> {
FixedNode next = pred.next();
pred.setNext(guard);
guard.setNext(next);
SimplifierTool simplifierTool = GraphUtil.getDefaultSimplifier(providers != null ? providers : EMPTY_PROVIDERS, false, graph.getAssumptions(), graph.getOptions());
assert providers != null;
SimplifierTool simplifierTool = GraphUtil.getDefaultSimplifier(providers, false, graph.getAssumptions(), graph.getOptions());
survivingSuccessor.simplify(simplifierTool);
}
}

View File

@ -732,12 +732,12 @@ public final class IfNode extends ControlSplitNode implements Simplifiable, LIRL
* Check it these two blocks end up at the same place. Meeting at the same merge, or
* deoptimizing in the same way.
*/
private static boolean sameDestination(AbstractBeginNode succ1, AbstractBeginNode succ2) {
public static boolean sameDestination(AbstractBeginNode succ1, AbstractBeginNode succ2) {
Node next1 = succ1.next();
Node next2 = succ2.next();
if (next1 instanceof EndNode && next2 instanceof EndNode) {
EndNode end1 = (EndNode) next1;
EndNode end2 = (EndNode) next2;
if (next1 instanceof AbstractEndNode && next2 instanceof AbstractEndNode) {
AbstractEndNode end1 = (AbstractEndNode) next1;
AbstractEndNode end2 = (AbstractEndNode) next2;
if (end1.merge() == end2.merge()) {
for (PhiNode phi : end1.merge().phis()) {
if (phi.valueAt(end1) != phi.valueAt(end2)) {
@ -1052,18 +1052,26 @@ public final class IfNode extends ControlSplitNode implements Simplifiable, LIRL
*/
private boolean isSafeConditionalInput(ValueNode value, AbstractBeginNode successor) {
assert successor.hasNoUsages();
if (value.isConstant() || value instanceof ParameterNode || condition.inputs().contains(value)) {
// Assume constants are cheap to evaluate and Parameters are always evaluated. Any input
// to the condition itself is also unconditionally evaluated.
if (value.isConstant() || condition.inputs().contains(value)) {
// Assume constants are cheap to evaluate. Any input to the condition itself is also
// unconditionally evaluated.
return true;
}
if (value instanceof FixedNode && graph().isAfterFixedReadPhase()) {
if (graph().isAfterFixedReadPhase()) {
if (value instanceof ParameterNode) {
// Assume Parameters are always evaluated but only apply this logic to graphs after
// inlining. Checking for ParameterNode causes it to apply to graphs which are going
// to be inlined into other graphs which is incorrect.
return true;
}
if (value instanceof FixedNode) {
List<Node> nodes = getNodesForBlock(successor);
// The successor block is empty so assume that this input evaluated before the
// condition.
return nodes != null && nodes.size() == 2;
}
}
return false;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -34,6 +34,7 @@ import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.core.common.type.TypeReference;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.graph.Node.NodeIntrinsicFactory;
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.graph.spi.Canonicalizable;
import org.graalvm.compiler.graph.spi.CanonicalizerTool;
@ -50,7 +51,6 @@ import org.graalvm.compiler.nodes.type.StampTool;
import org.graalvm.compiler.nodes.virtual.VirtualObjectNode;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.meta.ResolvedJavaType;
//JaCoCo Exclude
@ -64,6 +64,7 @@ import jdk.vm.ci.meta.ResolvedJavaType;
* also the scheduling restriction enforced by the guard, will go away.
*/
@NodeInfo(cycles = CYCLES_0, size = SIZE_0)
@NodeIntrinsicFactory
public class PiNode extends FloatingGuardedNode implements LIRLowerable, Virtualizable, Canonicalizable, ValueProxy {
public static final NodeClass<PiNode> TYPE = NodeClass.create(PiNode.class);
@ -124,8 +125,7 @@ public class PiNode extends FloatingGuardedNode implements LIRLowerable, Virtual
return new PiNode(object, stamp, guard);
}
@SuppressWarnings("unused")
public static boolean intrinsify(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode object, ValueNode guard) {
public static boolean intrinsify(GraphBuilderContext b, ValueNode object, ValueNode guard) {
Stamp stamp = AbstractPointerStamp.pointerNonNull(object.stamp(NodeView.DEFAULT));
ValueNode value = canonical(object, stamp, (GuardingNode) guard, null);
if (value == null) {
@ -135,8 +135,7 @@ public class PiNode extends FloatingGuardedNode implements LIRLowerable, Virtual
return true;
}
@SuppressWarnings("unused")
public static boolean intrinsify(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode object, ResolvedJavaType toType, boolean exactType, boolean nonNull) {
public static boolean intrinsify(GraphBuilderContext b, ValueNode object, ResolvedJavaType toType, boolean exactType, boolean nonNull) {
Stamp stamp = StampFactory.object(exactType ? TypeReference.createExactTrusted(toType) : TypeReference.createWithoutAssumptions(toType),
nonNull || StampTool.isPointerNonNull(object.stamp(NodeView.DEFAULT)));
ValueNode value = canonical(object, stamp, null, null);

View File

@ -0,0 +1,75 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.graalvm.compiler.nodes;
import java.util.Map;
import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.graph.NodeInputList;
import org.graalvm.compiler.nodeinfo.NodeCycles;
import org.graalvm.compiler.nodeinfo.NodeInfo;
import org.graalvm.compiler.nodeinfo.NodeSize;
import org.graalvm.compiler.nodeinfo.Verbosity;
import org.graalvm.compiler.nodes.graphbuilderconf.GeneratedPluginInjectionProvider;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
@NodeInfo(nameTemplate = "PluginReplacement/{p#pluginName}", cycles = NodeCycles.CYCLES_IGNORED, size = NodeSize.SIZE_IGNORED)
public final class PluginReplacementNode extends FixedWithNextNode {
public static final NodeClass<PluginReplacementNode> TYPE = NodeClass.create(PluginReplacementNode.class);
@Input protected NodeInputList<ValueNode> args;
private final ReplacementFunction function;
private final String pluginName;
public PluginReplacementNode(Stamp stamp, ValueNode[] args, ReplacementFunction function, String pluginName) {
super(TYPE, stamp);
this.args = new NodeInputList<>(this, args);
this.function = function;
this.pluginName = pluginName;
}
public boolean replace(GraphBuilderContext b, GeneratedPluginInjectionProvider injection) {
return function.replace(b, injection, stamp, args);
}
public interface ReplacementFunction {
boolean replace(GraphBuilderContext b, GeneratedPluginInjectionProvider injection, Stamp stamp, NodeInputList<ValueNode> args);
}
@Override
public String toString(Verbosity verbosity) {
if (verbosity == Verbosity.Short) {
return super.toString(verbosity) + "/" + pluginName;
}
return super.toString(verbosity);
}
@Override
public Map<Object, Object> getDebugProperties(Map<Object, Object> map) {
map.put("name", pluginName);
return super.getDebugProperties(map);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -442,6 +442,7 @@ public final class ControlFlowGraph implements AbstractControlFlowGraph<Block> {
assert nodeToBlock.get(cur) == null;
nodeToBlock.set(cur, block);
FixedNode next = cur.next();
assert next != null : cur;
if (next instanceof AbstractBeginNode) {
block.endNode = cur;
return;

View File

@ -64,6 +64,7 @@ public final class BytecodeExceptionNode extends AbstractMemoryCheckpoint implem
OUT_OF_BOUNDS(2, ArrayIndexOutOfBoundsException.class),
CLASS_CAST(2, ClassCastException.class),
ARRAY_STORE(1, ArrayStoreException.class),
ILLEGAL_ARGUMENT_EXCEPTION(1, IllegalArgumentException.class),
DIVISION_BY_ZERO(0, ArithmeticException.class),
INTEGER_EXACT_OVERFLOW(0, ArithmeticException.class),
LONG_EXACT_OVERFLOW(0, ArithmeticException.class);

View File

@ -36,6 +36,7 @@ import org.graalvm.compiler.core.common.spi.ForeignCallSignature;
import org.graalvm.compiler.core.common.spi.ForeignCallsProvider;
import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.graph.Node.NodeIntrinsicFactory;
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.graph.NodeInputList;
import org.graalvm.compiler.nodeinfo.NodeInfo;
@ -47,8 +48,6 @@ import org.graalvm.compiler.nodes.memory.AbstractMemoryCheckpoint;
import jdk.vm.ci.code.BytecodeFrame;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.meta.ResolvedJavaType;
/**
* Node for a {@linkplain ForeignCallDescriptor foreign} call.
@ -61,6 +60,7 @@ import jdk.vm.ci.meta.ResolvedJavaType;
size = SIZE_2,
sizeRationale = "Rough estimation of the call operation itself.")
// @formatter:on
@NodeIntrinsicFactory
public class ForeignCallNode extends AbstractMemoryCheckpoint implements ForeignCall {
public static final NodeClass<ForeignCallNode> TYPE = NodeClass.create(ForeignCallNode.class);
@ -70,17 +70,17 @@ public class ForeignCallNode extends AbstractMemoryCheckpoint implements Foreign
protected final ForeignCallDescriptor descriptor;
protected int bci = BytecodeFrame.UNKNOWN_BCI;
public static boolean intrinsify(GraphBuilderContext b, ResolvedJavaMethod targetMethod, @InjectedNodeParameter Stamp returnStamp, @InjectedNodeParameter ForeignCallsProvider foreignCalls,
public static boolean intrinsify(GraphBuilderContext b, @InjectedNodeParameter Stamp returnStamp, @InjectedNodeParameter ForeignCallsProvider foreignCalls,
ForeignCallSignature signature, ValueNode... arguments) {
ForeignCallDescriptor descriptor = foreignCalls.getDescriptor(signature);
return doIntrinsify(b, targetMethod, returnStamp, descriptor, arguments, false);
return doIntrinsify(b, returnStamp, descriptor, arguments, false);
}
public static boolean intrinsify(GraphBuilderContext b, ResolvedJavaMethod targetMethod, @InjectedNodeParameter Stamp returnStamp, ForeignCallDescriptor descriptor, ValueNode... arguments) {
return doIntrinsify(b, targetMethod, returnStamp, descriptor, arguments, false);
public static boolean intrinsify(GraphBuilderContext b, @InjectedNodeParameter Stamp returnStamp, ForeignCallDescriptor descriptor, ValueNode... arguments) {
return doIntrinsify(b, returnStamp, descriptor, arguments, false);
}
static boolean doIntrinsify(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Stamp returnStamp, ForeignCallDescriptor descriptor, ValueNode[] arguments, boolean withException) {
static boolean doIntrinsify(GraphBuilderContext b, Stamp returnStamp, ForeignCallDescriptor descriptor, ValueNode[] arguments, boolean withException) {
ForeignCall node;
if (withException) {
node = new ForeignCallWithExceptionNode(descriptor, arguments);
@ -89,8 +89,6 @@ public class ForeignCallNode extends AbstractMemoryCheckpoint implements Foreign
}
node.asNode().setStamp(returnStamp);
assert verifyDescriptor(b, targetMethod, descriptor);
/*
* Need to update the BCI of a ForeignCallNode so that it gets the stateDuring in the case
* that the foreign call can deoptimize. As with all deoptimization, we need a state in a
@ -101,7 +99,7 @@ public class ForeignCallNode extends AbstractMemoryCheckpoint implements Foreign
node.setBci(nonIntrinsicAncestor.bci());
}
JavaKind returnKind = targetMethod.getSignature().getReturnKind();
JavaKind returnKind = returnStamp.getStackKind();
if (returnKind == JavaKind.Void) {
b.add(node.asNode());
} else {
@ -111,17 +109,6 @@ public class ForeignCallNode extends AbstractMemoryCheckpoint implements Foreign
return true;
}
static boolean verifyDescriptor(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ForeignCallDescriptor descriptor) {
int parameters = 1;
for (Class<?> arg : descriptor.getArgumentTypes()) {
ResolvedJavaType res = b.getMetaAccess().lookupJavaType(arg);
ResolvedJavaType parameterType = (ResolvedJavaType) targetMethod.getSignature().getParameterType(parameters, targetMethod.getDeclaringClass());
assert parameterType.equals(res) : descriptor + ": parameter " + parameters + " mismatch: " + res + " != " + parameterType;
parameters++;
}
return true;
}
public ForeignCallNode(ForeignCallsProvider foreignCalls, ForeignCallSignature signature, ValueNode... arguments) {
this(TYPE, foreignCalls.getDescriptor(signature), arguments);
}

View File

@ -34,6 +34,7 @@ import java.util.Arrays;
import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.graph.Node.NodeIntrinsicFactory;
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.graph.NodeInputList;
import org.graalvm.compiler.graph.spi.Simplifiable;
@ -52,7 +53,6 @@ import org.graalvm.compiler.nodes.util.GraphUtil;
import jdk.vm.ci.code.BytecodeFrame;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.ResolvedJavaMethod;
/**
* Node for a {@linkplain ForeignCallDescriptor foreign} call with an {@linkplain WithExceptionNode
@ -66,6 +66,7 @@ import jdk.vm.ci.meta.ResolvedJavaMethod;
size = SIZE_2,
sizeRationale = "Rough estimation of the call operation itself.")
// @formatter:on
@NodeIntrinsicFactory
public class ForeignCallWithExceptionNode extends WithExceptionNode implements ForeignCall, Simplifiable {
public static final NodeClass<ForeignCallWithExceptionNode> TYPE = NodeClass.create(ForeignCallWithExceptionNode.class);
@ -76,8 +77,8 @@ public class ForeignCallWithExceptionNode extends WithExceptionNode implements F
protected final ForeignCallDescriptor descriptor;
protected int bci = BytecodeFrame.UNKNOWN_BCI;
public static boolean intrinsify(GraphBuilderContext b, ResolvedJavaMethod targetMethod, @InjectedNodeParameter Stamp returnStamp, ForeignCallDescriptor descriptor, ValueNode... arguments) {
return ForeignCallNode.doIntrinsify(b, targetMethod, returnStamp, descriptor, arguments, true);
public static boolean intrinsify(GraphBuilderContext b, @InjectedNodeParameter Stamp returnStamp, ForeignCallDescriptor descriptor, ValueNode... arguments) {
return ForeignCallNode.doIntrinsify(b, returnStamp, descriptor, arguments, true);
}
public ForeignCallWithExceptionNode(ForeignCallDescriptor descriptor, ValueNode... arguments) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -26,20 +26,21 @@ package org.graalvm.compiler.nodes.extended;
import org.graalvm.compiler.graph.Node.ConstantNodeParameter;
import org.graalvm.compiler.graph.Node.NodeIntrinsic;
import org.graalvm.compiler.graph.Node.NodeIntrinsicFactory;
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.ResolvedJavaMethod;
/**
* Copy a value at a location specified as an offset relative to a source object to another location
* specified as an offset relative to destination object. No null checks are performed.
*/
@NodeIntrinsicFactory
public final class UnsafeCopyNode {
public static boolean intrinsify(GraphBuilderContext b, @SuppressWarnings("unused") ResolvedJavaMethod targetMethod, ValueNode sourceObject, ValueNode sourceOffset, ValueNode destinationObject,
public static boolean intrinsify(GraphBuilderContext b, ValueNode sourceObject, ValueNode sourceOffset, ValueNode destinationObject,
ValueNode destinationOffset, JavaKind accessKind, LocationIdentity locationIdentity) {
RawLoadNode value = b.add(new RawLoadNode(sourceObject, sourceOffset, accessKind, locationIdentity));
b.add(new RawStoreNode(destinationObject, destinationOffset, value, accessKind, locationIdentity));

View File

@ -0,0 +1,29 @@
/*
* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* 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.nodes.graphbuilderconf;
public abstract class GeneratedFoldInvocationPlugin extends GeneratedInvocationPlugin {
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -33,6 +33,7 @@ import java.lang.reflect.Method;
import org.graalvm.compiler.api.replacements.Fold;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.graph.Node.NodeIntrinsic;
import org.graalvm.compiler.nodes.PluginReplacementNode;
import org.graalvm.compiler.nodes.ValueNode;
import jdk.vm.ci.meta.MetaAccessProvider;
@ -80,16 +81,24 @@ public abstract class GeneratedInvocationPlugin implements InvocationPlugin {
return false;
}
ResolvedJavaMethod thisExecuteMethod = getExecutedMethod(b);
if (b.getMethod().equals(thisExecuteMethod)) {
// The "execute" method of this plugin is itself being compiled. In (only) this context,
// the injected argument of the call to the @Fold annotated method will be non-null.
if (IS_BUILDING_NATIVE_IMAGE) {
// The use of this plugin in the plugin itself shouldn't be folded since that defeats
// the purpose of the fold.
ResolvedJavaType foldNodeClass = b.getMetaAccess().lookupJavaType(PluginReplacementNode.ReplacementFunction.class);
if (foldNodeClass.isAssignableFrom(b.getMethod().getDeclaringClass())) {
return false;
}
ResolvedJavaType foldPluginClass = b.getMetaAccess().lookupJavaType(GeneratedFoldInvocationPlugin.class);
if (foldPluginClass.isAssignableFrom(b.getMethod().getDeclaringClass())) {
return false;
}
}
ResolvedJavaMethod thisExecuteMethod = getExecutedMethod(b);
if (b.getMethod().equals(thisExecuteMethod)) {
return true;
}
throw new AssertionError("must pass null to injected argument of " + foldAnnotatedMethod.format("%H.%n(%p)") + ", not " + arg);
throw new AssertionError("must pass null to injected argument of " + foldAnnotatedMethod.format("%H.%n(%p)") + ", not " + arg + " in " + b.getMethod().format("%H.%n(%p)"));
}
private ResolvedJavaMethod getExecutedMethod(GraphBuilderContext b) {

View File

@ -0,0 +1,45 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.graalvm.compiler.nodes.graphbuilderconf;
import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
import jdk.vm.ci.meta.MetaAccessProvider;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.meta.ResolvedJavaType;
public abstract class GeneratedNodeIntrinsicInvocationPlugin extends GeneratedInvocationPlugin {
protected boolean verifyForeignCallDescriptor(GraphBuilderTool b, ResolvedJavaMethod targetMethod, ForeignCallDescriptor descriptor) {
MetaAccessProvider metaAccess = b.getMetaAccess();
int parameters = 1;
for (Class<?> arg : descriptor.getArgumentTypes()) {
ResolvedJavaType res = metaAccess.lookupJavaType(arg);
ResolvedJavaType parameterType = (ResolvedJavaType) targetMethod.getSignature().getParameterType(parameters, targetMethod.getDeclaringClass());
assert parameterType.equals(res) : descriptor + ": parameter " + parameters + " mismatch: " + res + " != " + parameterType;
parameters++;
}
return true;
}
}

View File

@ -0,0 +1,30 @@
/*
* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* 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.nodes.graphbuilderconf;
public interface GeneratedPluginFactory {
void registerPlugins(InvocationPlugins plugins, GeneratedPluginInjectionProvider injection);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -26,9 +26,7 @@ package org.graalvm.compiler.nodes.graphbuilderconf;
import org.graalvm.compiler.core.common.type.Stamp;
public interface NodeIntrinsicPluginFactory {
public interface InjectionProvider {
public interface GeneratedPluginInjectionProvider {
<T> T getInjectedArgument(Class<T> type);
@ -41,6 +39,3 @@ public interface NodeIntrinsicPluginFactory {
*/
Stamp getInjectedStamp(Class<?> type, boolean nonNull);
}
void registerPlugins(InvocationPlugins plugins, InjectionProvider injection);
}

View File

@ -48,6 +48,7 @@ import org.graalvm.compiler.nodes.Invoke;
import org.graalvm.compiler.nodes.LogicNode;
import org.graalvm.compiler.nodes.NodeView;
import org.graalvm.compiler.nodes.PiNode;
import org.graalvm.compiler.nodes.PluginReplacementNode;
import org.graalvm.compiler.nodes.StateSplit;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.ValueNode;
@ -377,6 +378,17 @@ public interface GraphBuilderContext extends GraphBuilderTool {
default AbstractBeginNode genExplicitExceptionEdge(@SuppressWarnings("ununsed") BytecodeExceptionKind exceptionKind) {
return null;
}
/**
*
* @param plugin
* @param targetMethod
* @param args
* @param replacementFunction
*/
default void replacePlugin(GeneratedInvocationPlugin plugin, ResolvedJavaMethod targetMethod, ValueNode[] args, PluginReplacementNode.ReplacementFunction replacementFunction) {
throw GraalError.unimplemented();
}
}
class GraphBuilderContextUtil {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -87,4 +87,10 @@ public interface GraphBuilderTool {
// By default generated plugins must be completely processed during parsing.
return false;
}
@SuppressWarnings("unused")
default boolean shouldDeferPlugin(GeneratedInvocationPlugin plugin) {
// By default generated plugins must be completely processed during parsing.
return false;
}
}

View File

@ -106,7 +106,7 @@ public class DynamicNewArrayNode extends AbstractNewArrayNode implements Canonic
return this;
}
ResolvedJavaType type = tool.getConstantReflection().asJavaType(elementType.asConstant());
if (type != null && !throwsIllegalArgumentException(type) && tool.getMetaAccessExtensionProvider().canConstantFoldDynamicAllocation(type)) {
if (type != null && !throwsIllegalArgumentException(type) && tool.getMetaAccessExtensionProvider().canConstantFoldDynamicAllocation(type.getArrayClass())) {
return createNewArrayNode(type);
}
}

View File

@ -34,6 +34,7 @@ import org.graalvm.compiler.core.common.type.ObjectStamp;
import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.core.common.type.TypeReference;
import org.graalvm.compiler.graph.Node.NodeIntrinsicFactory;
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.graph.spi.CanonicalizerTool;
import org.graalvm.compiler.nodeinfo.NodeInfo;
@ -54,7 +55,6 @@ import org.graalvm.compiler.nodes.type.StampTool;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.JavaTypeProfile;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.meta.ResolvedJavaType;
import jdk.vm.ci.meta.TriState;
@ -62,6 +62,7 @@ import jdk.vm.ci.meta.TriState;
* The {@code InstanceOfNode} represents an instanceof test.
*/
@NodeInfo(cycles = CYCLES_8, size = SIZE_8)
@NodeIntrinsicFactory
public class InstanceOfNode extends UnaryOpLogicNode implements Lowerable, Virtualizable {
public static final NodeClass<InstanceOfNode> TYPE = NodeClass.create(InstanceOfNode.class);
@ -220,8 +221,7 @@ public class InstanceOfNode extends UnaryOpLogicNode implements Lowerable, Virtu
@NodeIntrinsic
public static native boolean doInstanceof(@ConstantNodeParameter ResolvedJavaType type, Object object);
@SuppressWarnings("unused")
static boolean intrinsify(GraphBuilderContext b, ResolvedJavaMethod method, ResolvedJavaType type, ValueNode object) {
public static boolean intrinsify(GraphBuilderContext b, ResolvedJavaType type, ValueNode object) {
InstanceOfNode node = new InstanceOfNode(StampFactory.objectNonNull(TypeReference.create(b.getAssumptions(), type)), object, null, null);
node = b.add(node);
b.addPush(JavaKind.Int, ConditionalNode.create(node, NodeView.DEFAULT));

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -38,6 +38,7 @@ import org.graalvm.compiler.nodeinfo.Verbosity;
import org.graalvm.compiler.nodes.BeginNode;
import org.graalvm.compiler.nodes.CallTargetNode;
import org.graalvm.compiler.nodes.FixedGuardNode;
import org.graalvm.compiler.nodes.FixedNode;
import org.graalvm.compiler.nodes.Invoke;
import org.graalvm.compiler.nodes.LogicNode;
import org.graalvm.compiler.nodes.NodeView;
@ -177,29 +178,36 @@ public class MethodCallTargetNode extends CallTargetNode implements IterableNode
return;
}
Assumptions assumptions = graph().getAssumptions();
/*
* Even though we are not registering an assumption (see comment below), the optimization is
* only valid when speculative optimizations are enabled.
*/
if (invokeKind().isIndirect() && invokeKind().isInterface() && assumptions != null) {
if (invokeKind.isInterface()) {
MethodCallTargetNode result = tryDevirtualizeInterfaceCall(receiver(), targetMethod, profile, graph().getAssumptions(), contextType, this, invoke().asNode());
assert result == this;
}
}
// check if the type of the receiver can narrow the result
ValueNode receiver = receiver();
public static MethodCallTargetNode tryDevirtualizeInterfaceCall(ValueNode receiver, ResolvedJavaMethod targetMethod, JavaTypeProfile profile, Assumptions assumptions, ResolvedJavaType contextType,
MethodCallTargetNode callTarget, FixedNode insertionPoint) {
if (assumptions == null) {
/*
* Even though we are not registering an assumption (see comment below), the
* optimization is only valid when speculative optimizations are enabled.
*/
return callTarget;
}
// try to turn a interface call into a virtual call
ResolvedJavaType declaredReceiverType = targetMethod().getDeclaringClass();
ResolvedJavaType declaredReceiverType = targetMethod.getDeclaringClass();
/*
* We need to check the invoke kind to avoid recursive simplification for virtual
* interface methods calls.
* We need to check the invoke kind to avoid recursive simplification for virtual interface
* methods calls.
*/
if (declaredReceiverType.isInterface()) {
ResolvedJavaType singleImplementor = declaredReceiverType.getSingleImplementor();
if (singleImplementor != null && !singleImplementor.equals(declaredReceiverType)) {
TypeReference speculatedType = TypeReference.createTrusted(assumptions, singleImplementor);
if (tryCheckCastSingleImplementor(receiver, speculatedType)) {
return;
MethodCallTargetNode callTargetResult = tryCheckCastSingleImplementor(receiver, targetMethod, profile, contextType, speculatedType, insertionPoint, callTarget);
if (callTargetResult != null) {
return callTargetResult;
}
}
}
@ -210,19 +218,24 @@ public class MethodCallTargetNode extends CallTargetNode implements IterableNode
if (uncheckedStamp != null) {
TypeReference speculatedType = StampTool.typeReferenceOrNull(uncheckedStamp);
if (speculatedType != null) {
tryCheckCastSingleImplementor(receiver, speculatedType);
MethodCallTargetNode callTargetResult = tryCheckCastSingleImplementor(receiver, targetMethod, profile, contextType, speculatedType, insertionPoint, callTarget);
if (callTargetResult != null) {
return callTargetResult;
}
}
}
}
return callTarget;
}
private boolean tryCheckCastSingleImplementor(ValueNode receiver, TypeReference speculatedType) {
private static MethodCallTargetNode tryCheckCastSingleImplementor(ValueNode receiver, ResolvedJavaMethod targetMethod, JavaTypeProfile profile, ResolvedJavaType contextType,
TypeReference speculatedType,
FixedNode insertionPoint, MethodCallTargetNode callTarget) {
ResolvedJavaType singleImplementor = speculatedType.getType();
if (singleImplementor != null) {
ResolvedJavaMethod singleImplementorMethod = singleImplementor.resolveConcreteMethod(targetMethod(), invoke().getContextType());
ResolvedJavaMethod singleImplementorMethod = singleImplementor.resolveConcreteMethod(targetMethod, contextType);
if (singleImplementorMethod != null) {
/**
/*
* We have an invoke on an interface with a single implementor. We can replace this
* with an invoke virtual.
*
@ -233,22 +246,32 @@ public class MethodCallTargetNode extends CallTargetNode implements IterableNode
* an assumption but as we need an instanceof check anyway we can verify both
* properties by checking of the receiver is an instance of the single implementor.
*/
AnchoringNode anchor = BeginNode.prevBegin(invoke().asNode());
LogicNode condition = graph().addOrUniqueWithInputs(InstanceOfNode.create(speculatedType, receiver, getProfile(), anchor));
FixedGuardNode guard = graph().add(new FixedGuardNode(condition, DeoptimizationReason.OptimizedTypeCheckViolated, DeoptimizationAction.InvalidateRecompile, false));
graph().addBeforeFixed(invoke().asNode(), guard);
ValueNode valueNode = graph().addOrUnique(new PiNode(receiver, StampFactory.objectNonNull(speculatedType), guard));
arguments().set(0, valueNode);
StructuredGraph graph = insertionPoint.graph();
AnchoringNode anchor = BeginNode.prevBegin(insertionPoint);
LogicNode condition = graph.addOrUniqueWithInputs(InstanceOfNode.create(speculatedType, receiver, profile, anchor));
FixedGuardNode guard = graph.add(new FixedGuardNode(condition, DeoptimizationReason.OptimizedTypeCheckViolated, DeoptimizationAction.InvalidateRecompile, false));
graph.addBeforeFixed(insertionPoint, guard);
InvokeKind invokeKind;
if (speculatedType.isExact()) {
setInvokeKind(InvokeKind.Special);
invokeKind = InvokeKind.Special;
} else {
setInvokeKind(InvokeKind.Virtual);
invokeKind = InvokeKind.Virtual;
}
setTargetMethod(singleImplementorMethod);
return true;
MethodCallTargetNode callTargetResult = callTarget;
ValueNode valueNode = graph.addOrUnique(new PiNode(receiver, StampFactory.objectNonNull(speculatedType), guard));
if (callTarget.isAlive()) {
callTarget.arguments().set(0, valueNode);
callTargetResult.setInvokeKind(invokeKind);
callTargetResult.setTargetMethod(singleImplementorMethod);
} else {
ValueNode[] arguments = callTarget.arguments().toArray(new ValueNode[callTarget.arguments().size()]);
arguments[0] = valueNode;
callTargetResult = new MethodCallTargetNode(invokeKind, singleImplementorMethod, arguments, callTarget.returnStamp, profile);
}
return callTargetResult;
}
}
return false;
return null;
}
public JavaTypeProfile getProfile() {

View File

@ -100,4 +100,20 @@ public class CoreProvidersImpl implements CoreProviders {
public MetaAccessExtensionProvider getMetaAccessExtensionProvider() {
return metaAccessExtensionProvider;
}
public CoreProvidersImpl copyWith(ConstantReflectionProvider substitution) {
assert this.getClass() == CoreProvidersImpl.class : "must override in " + getClass();
return new CoreProvidersImpl(metaAccess, substitution, constantFieldProvider, lowerer, replacements, stampProvider, foreignCalls, platformConfigurationProvider, metaAccessExtensionProvider);
}
public CoreProvidersImpl copyWith(ConstantFieldProvider substitution) {
assert this.getClass() == CoreProvidersImpl.class : "must override in " + getClass();
return new CoreProvidersImpl(metaAccess, constantReflection, substitution, lowerer, replacements, stampProvider, foreignCalls, platformConfigurationProvider, metaAccessExtensionProvider);
}
public CoreProvidersImpl copyWith(Replacements substitution) {
assert this.getClass() == CoreProvidersImpl.class : "must override in " + getClass();
return new CoreProvidersImpl(metaAccess, constantReflection, constantFieldProvider, lowerer, substitution, stampProvider, foreignCalls, platformConfigurationProvider,
metaAccessExtensionProvider);
}
}

View File

@ -27,6 +27,7 @@ package org.graalvm.compiler.nodes.spi;
import org.graalvm.compiler.api.replacements.SnippetTemplateCache;
import org.graalvm.compiler.bytecode.BytecodeProvider;
import org.graalvm.compiler.core.common.CompilationIdentifier;
import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.graph.NodeSourcePosition;
import org.graalvm.compiler.nodes.Cancellable;
@ -56,6 +57,16 @@ public class DelegatingReplacements implements Replacements {
return delegate.getProviders();
}
@Override
public <T> T getInjectedArgument(Class<T> type) {
return delegate.getInjectedArgument(type);
}
@Override
public Stamp getInjectedStamp(Class<?> type, boolean nonNull) {
return delegate.getInjectedStamp(type, nonNull);
}
@Override
public GraphBuilderConfiguration.Plugins getGraphBuilderPlugins() {
return delegate.getGraphBuilderPlugins();
@ -82,6 +93,11 @@ public class DelegatingReplacements implements Replacements {
return delegate.isSnippet(method);
}
@Override
public boolean isEncodingSnippets() {
return delegate.isEncodingSnippets();
}
@Override
public void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, boolean trackNodeSourcePosition, OptionValues options) {
delegate.registerSnippet(method, original, receiver, trackNodeSourcePosition, options);

View File

@ -33,6 +33,7 @@ import org.graalvm.compiler.graph.NodeSourcePosition;
import org.graalvm.compiler.nodes.Cancellable;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
import org.graalvm.compiler.nodes.graphbuilderconf.GeneratedPluginInjectionProvider;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderPlugin;
import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext;
@ -45,7 +46,7 @@ import jdk.vm.ci.meta.ResolvedJavaMethod;
/**
* Interface for managing replacements.
*/
public interface Replacements {
public interface Replacements extends GeneratedPluginInjectionProvider {
CoreProviders getProviders();
@ -84,6 +85,14 @@ public interface Replacements {
*/
boolean isSnippet(ResolvedJavaMethod method);
/**
* Returns {@code true} if this {@code Replacements} is being used for preparation of snippets
* and substitutions for libgraal.
*/
default boolean isEncodingSnippets() {
return false;
}
/**
* Registers a method as snippet.
*/

View File

@ -41,6 +41,7 @@ import org.graalvm.compiler.bytecode.Bytecode;
import org.graalvm.compiler.code.SourceStackTraceBailoutException;
import org.graalvm.compiler.core.common.type.ObjectStamp;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.graph.Graph;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.graph.NodeBitMap;
@ -55,6 +56,7 @@ import org.graalvm.compiler.nodes.AbstractMergeNode;
import org.graalvm.compiler.nodes.ConstantNode;
import org.graalvm.compiler.nodes.ControlSinkNode;
import org.graalvm.compiler.nodes.ControlSplitNode;
import org.graalvm.compiler.nodes.EndNode;
import org.graalvm.compiler.nodes.FixedNode;
import org.graalvm.compiler.nodes.FixedWithNextNode;
import org.graalvm.compiler.nodes.FrameState;
@ -63,6 +65,7 @@ import org.graalvm.compiler.nodes.IfNode;
import org.graalvm.compiler.nodes.LoopBeginNode;
import org.graalvm.compiler.nodes.LoopEndNode;
import org.graalvm.compiler.nodes.LoopExitNode;
import org.graalvm.compiler.nodes.MergeNode;
import org.graalvm.compiler.nodes.NodeView;
import org.graalvm.compiler.nodes.PhiNode;
import org.graalvm.compiler.nodes.PiNode;
@ -73,9 +76,11 @@ import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.ValuePhiNode;
import org.graalvm.compiler.nodes.ValueProxyNode;
import org.graalvm.compiler.nodes.WithExceptionNode;
import org.graalvm.compiler.nodes.extended.MultiGuardNode;
import org.graalvm.compiler.nodes.java.LoadIndexedNode;
import org.graalvm.compiler.nodes.java.MethodCallTargetNode;
import org.graalvm.compiler.nodes.java.MonitorIdNode;
import org.graalvm.compiler.nodes.memory.MemoryPhiNode;
import org.graalvm.compiler.nodes.spi.ArrayLengthProvider;
import org.graalvm.compiler.nodes.spi.ArrayLengthProvider.FindLengthMode;
import org.graalvm.compiler.nodes.spi.CoreProviders;
@ -124,7 +129,7 @@ public class GraphUtil {
debug.dump(DebugContext.DETAILED_LEVEL, node.graph(), "After fixing merges (killCFG %s)", node);
// Mark non-fixed nodes
markUsages(markedNodes);
markUsagesForKill(markedNodes);
// Detach marked nodes from non-marked nodes
for (Node marked : markedNodes) {
@ -223,19 +228,37 @@ public class GraphUtil {
}
}
private static void markUsages(EconomicSet<Node> markedNodes) {
private static void markUsagesForKill(EconomicSet<Node> markedNodes) {
NodeStack workStack = new NodeStack(markedNodes.size() + 4);
for (Node marked : markedNodes) {
workStack.push(marked);
}
ArrayList<MultiGuardNode> unmarkedMultiGuards = new ArrayList<>();
while (!workStack.isEmpty()) {
Node marked = workStack.pop();
for (Node usage : marked.usages()) {
if (!markedNodes.contains(usage)) {
boolean doMark = true;
if (usage instanceof MultiGuardNode) {
// Only mark a MultiGuardNode for deletion if all of its guards are marked for
// deletion. Otherwise, we would kill nodes outside the path to be killed.
MultiGuardNode multiGuard = (MultiGuardNode) usage;
for (Node guard : multiGuard.inputs()) {
if (!markedNodes.contains(guard)) {
doMark = false;
unmarkedMultiGuards.add(multiGuard);
}
}
}
if (doMark && !markedNodes.contains(usage)) {
workStack.push(usage);
markedNodes.add(usage);
}
}
// Detach unmarked multi guards from the marked node
for (MultiGuardNode multiGuard : unmarkedMultiGuards) {
multiGuard.replaceFirstInput(marked, null);
}
unmarkedMultiGuards.clear();
}
}
@ -1144,4 +1167,74 @@ public class GraphUtil {
public static boolean mayRemoveSplit(IfNode ifNode) {
return GraphUtil.checkFrameState(ifNode.trueSuccessor(), MAX_FRAMESTATE_SEARCH_DEPTH) && GraphUtil.checkFrameState(ifNode.falseSuccessor(), MAX_FRAMESTATE_SEARCH_DEPTH);
}
/**
* An if node with an empty body at the end of a loop is represented with a {@link LoopEndNode}
* at the end of each path. For some optimizations it is more useful to have a representation of
* the if statement as a proper diamond with a merge after the two bodies, followed by a
* {@link LoopEndNode}. This method tries to transform the given {@code ifNode} into such a
* form, introducing new phi nodes for the diamond and patching up the loop's phis accordingly.
* On success, the newly introduced loop end node is returned. If the given {@code ifNode} is
* not an if statement with empty bodies at the end of the loop, the graph is not modified, and
* {@code null} is returned.
*
* Note that the diamond representation is not canonical and will be undone by the next
* application of {@link LoopEndNode#simplify(SimplifierTool)}.
*/
public static LoopEndNode tryToTransformToEmptyLoopDiamond(IfNode ifNode, LoopBeginNode loopBegin) {
if (ifNode.trueSuccessor().next() instanceof AbstractEndNode && ifNode.falseSuccessor().next() instanceof AbstractEndNode) {
AbstractEndNode trueEnd = (AbstractEndNode) ifNode.trueSuccessor().next();
AbstractEndNode falseEnd = (AbstractEndNode) ifNode.falseSuccessor().next();
if (trueEnd.merge() == loopBegin && falseEnd.merge() == loopBegin) {
StructuredGraph graph = loopBegin.graph();
for (PhiNode phi : loopBegin.phis()) {
if (!(phi instanceof ValuePhiNode || phi instanceof MemoryPhiNode)) {
return null;
}
}
EndNode newTrueEnd = graph.add(new EndNode());
EndNode newFalseEnd = graph.add(new EndNode());
MergeNode merge = graph.add(new MergeNode());
merge.addForwardEnd(newTrueEnd);
merge.addForwardEnd(newFalseEnd);
ArrayList<PhiNode> replacementPhis = new ArrayList<>(loopBegin.phis().count());
for (PhiNode phi : loopBegin.phis()) {
if (phi instanceof ValuePhiNode) {
ValuePhiNode valuePhi = (ValuePhiNode) phi;
ValuePhiNode newPhi = phi.graph().unique(new ValuePhiNode(valuePhi.stamp(NodeView.DEFAULT), merge, new ValueNode[]{valuePhi.valueAt(trueEnd), valuePhi.valueAt(falseEnd)}));
replacementPhis.add(newPhi);
} else if (phi instanceof MemoryPhiNode) {
MemoryPhiNode memoryPhi = (MemoryPhiNode) phi;
MemoryPhiNode newPhi = phi.graph().unique(new MemoryPhiNode(merge, memoryPhi.getLocationIdentity(), new ValueNode[]{memoryPhi.valueAt(trueEnd), memoryPhi.valueAt(falseEnd)}));
replacementPhis.add(newPhi);
} else {
GraalError.shouldNotReachHere();
}
}
loopBegin.removeEnd(trueEnd);
loopBegin.removeEnd(falseEnd);
ifNode.trueSuccessor().setNext(newTrueEnd);
ifNode.falseSuccessor().setNext(newFalseEnd);
trueEnd.safeDelete();
falseEnd.safeDelete();
LoopEndNode newEnd = graph.add(new LoopEndNode(loopBegin));
merge.setNext(newEnd);
int i = 0;
for (PhiNode phi : loopBegin.phis()) {
ValueNode replacementPhi = replacementPhis.get(i);
assert (phi instanceof ValuePhiNode && replacementPhi instanceof ValuePhiNode) || (phi instanceof MemoryPhiNode && replacementPhi instanceof MemoryPhiNode);
phi.addInput(replacementPhi);
i++;
}
assert i == replacementPhis.size() : "did not consume all values";
return newEnd;
}
}
return null;
}
}

View File

@ -129,7 +129,12 @@ public class OptionsParser {
msg.format("%n %s=<value>", match.getName());
}
}
throw new IllegalArgumentException(msg.toString());
IllegalArgumentException iae = new IllegalArgumentException(msg.toString());
if (isFromLibGraal(iae)) {
msg.format("%nIf %s is a libgraal option, it must be specified with '-Dlibgraal.%s' as opposed to '-Dgraal.%s'.", name, name, name);
iae = new IllegalArgumentException(msg.toString());
}
throw iae;
}
Object value = parseOptionValue(desc, uncheckedValue);
@ -137,6 +142,15 @@ public class OptionsParser {
desc.getOptionKey().update(values, value);
}
private static boolean isFromLibGraal(Throwable t) {
for (StackTraceElement frame : t.getStackTrace()) {
if ("jdk.internal.vm.compiler.libgraal.LibGraal".equals(frame.getClassName())) {
return true;
}
}
return false;
}
/** Parses a given option value with a known descriptor. */
public static Object parseOptionValue(OptionDescriptor desc, Object uncheckedValue) {
Class<?> optionType = desc.getOptionValueType();

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -28,6 +28,7 @@ import jdk.internal.vm.compiler.collections.EconomicSet;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind;
import org.graalvm.compiler.nodes.Invoke;
import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.phases.common.inlining.InliningUtil;
import org.graalvm.compiler.phases.util.Providers;
@ -48,7 +49,7 @@ public class AssumptionInlineInfo extends ExactInlineInfo {
}
@Override
public EconomicSet<Node> inline(Providers providers, String reason) {
public EconomicSet<Node> inline(CoreProviders providers, String reason) {
takenAssumption.recordTo(invoke.asNode().graph().getAssumptions());
return super.inline(providers, reason);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -27,6 +27,7 @@ package org.graalvm.compiler.phases.common.inlining.info;
import jdk.internal.vm.compiler.collections.EconomicSet;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.nodes.Invoke;
import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.phases.common.inlining.info.elem.Inlineable;
import org.graalvm.compiler.phases.util.Providers;
@ -53,7 +54,7 @@ public class ExactInlineInfo extends AbstractInlineInfo {
}
@Override
public EconomicSet<Node> inline(Providers providers, String reason) {
public EconomicSet<Node> inline(CoreProviders providers, String reason) {
return inline(invoke, concrete, inlineableElement, !suppressNullCheck, reason);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -28,6 +28,7 @@ import jdk.internal.vm.compiler.collections.EconomicSet;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.nodes.Invoke;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
import org.graalvm.compiler.phases.common.inlining.info.elem.Inlineable;
@ -77,7 +78,7 @@ public interface InlineInfo {
*
* @return a collection of nodes that need to be canonicalized after the inlining
*/
EconomicSet<Node> inline(Providers providers, String reason);
EconomicSet<Node> inline(CoreProviders providers, String reason);
/**
* Try to make the call static bindable to avoid interface and virtual method calls.

View File

@ -53,6 +53,7 @@ import org.graalvm.compiler.nodes.extended.LoadHubNode;
import org.graalvm.compiler.nodes.java.ExceptionObjectNode;
import org.graalvm.compiler.nodes.java.MethodCallTargetNode;
import org.graalvm.compiler.nodes.java.TypeSwitchNode;
import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.nodes.spi.StampProvider;
import org.graalvm.compiler.nodes.util.GraphUtil;
import org.graalvm.compiler.phases.common.inlining.InliningUtil;
@ -158,7 +159,7 @@ public class MultiTypeGuardInlineInfo extends AbstractInlineInfo {
}
@Override
public EconomicSet<Node> inline(Providers providers, String reason) {
public EconomicSet<Node> inline(CoreProviders providers, String reason) {
if (hasSingleMethod()) {
return inlineSingleMethod(graph(), providers.getStampProvider(), providers.getConstantReflection(), reason);
} else {
@ -184,7 +185,7 @@ public class MultiTypeGuardInlineInfo extends AbstractInlineInfo {
return notRecordedTypeProbability > 0;
}
private EconomicSet<Node> inlineMultipleMethods(StructuredGraph graph, Providers providers, String reason) {
private EconomicSet<Node> inlineMultipleMethods(StructuredGraph graph, CoreProviders providers, String reason) {
int numberOfMethods = concretes.size();
FixedNode continuation = invoke.next();

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -38,6 +38,7 @@ import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.calc.CompareNode;
import org.graalvm.compiler.nodes.extended.LoadHubNode;
import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.phases.common.inlining.InliningUtil;
import org.graalvm.compiler.phases.common.inlining.info.elem.Inlineable;
import org.graalvm.compiler.phases.util.Providers;
@ -101,7 +102,7 @@ public class TypeGuardInlineInfo extends AbstractInlineInfo {
}
@Override
public EconomicSet<Node> inline(Providers providers, String reason) {
public EconomicSet<Node> inline(CoreProviders providers, String reason) {
createGuard(graph(), providers);
return inline(invoke, concrete, inlineableElement, false, reason);
}
@ -113,7 +114,7 @@ public class TypeGuardInlineInfo extends AbstractInlineInfo {
}
@SuppressWarnings("try")
private void createGuard(StructuredGraph graph, Providers providers) {
private void createGuard(StructuredGraph graph, CoreProviders providers) {
try (DebugCloseable context = invoke.asNode().withNodeSourcePosition()) {
ValueNode nonNullReceiver = InliningUtil.nonNullReceiver(invoke);
LoadHubNode receiverHub = graph.unique(new LoadHubNode(providers.getStampProvider(), nonNullReceiver));

View File

@ -68,7 +68,6 @@ import org.graalvm.compiler.phases.common.inlining.info.elem.Inlineable;
import org.graalvm.compiler.phases.common.inlining.info.elem.InlineableGraph;
import org.graalvm.compiler.phases.common.inlining.policy.InliningPolicy;
import org.graalvm.compiler.phases.tiers.HighTierContext;
import org.graalvm.compiler.phases.util.Providers;
import jdk.vm.ci.code.BailoutException;
import jdk.vm.ci.meta.Assumptions.AssumptionResult;
@ -412,7 +411,7 @@ public class InliningData {
try (DebugContext.Scope scope = debug.scope("doInline", callerGraph)) {
EconomicSet<Node> canonicalizedNodes = EconomicSet.create(Equivalence.IDENTITY);
canonicalizedNodes.addAll(calleeInfo.invoke().asNode().usages());
EconomicSet<Node> parameterUsages = calleeInfo.inline(new Providers(context), reason);
EconomicSet<Node> parameterUsages = calleeInfo.inline(context.getProviders(), reason);
canonicalizedNodes.addAll(parameterUsages);
counterInliningRuns.increment(debug);
debug.dump(DebugContext.DETAILED_LEVEL, callerGraph, "after %s", calleeInfo);
@ -468,7 +467,7 @@ public class InliningData {
}
if (context.getOptimisticOptimizations().devirtualizeInvokes(calleeInfo.graph().getOptions())) {
calleeInfo.tryToDevirtualizeInvoke(new Providers(context));
calleeInfo.tryToDevirtualizeInvoke(context.getProviders());
}
return false;
@ -496,7 +495,7 @@ public class InliningData {
* <p>
* The {@link InlineInfo} used to get things rolling is kept around in the
* {@link MethodInvocation}, it will be needed in case of inlining, see
* {@link InlineInfo#inline(Providers, String)}
* {@link InlineInfo#inline(org.graalvm.compiler.nodes.spi.CoreProviders, String)}
* </p>
*/
private void processNextInvoke() {

Some files were not shown because too many files have changed in this diff Show More