use of org.graalvm.compiler.nodes.extended.ValueAnchorNode in project graal by oracle.
the class MethodHandleNode method maybeCastArgument.
/**
* Inserts a node to cast the argument at index to the given type if the given type is more
* concrete than the argument type.
*
* @param adder
* @param index of the argument to be cast
* @param type the type the argument should be cast to
*/
private static void maybeCastArgument(GraphAdder adder, ValueNode[] arguments, int index, JavaType type) {
ValueNode argument = arguments[index];
if (type instanceof ResolvedJavaType && !((ResolvedJavaType) type).isJavaLangObject()) {
Assumptions assumptions = adder.getAssumptions();
TypeReference targetType = TypeReference.create(assumptions, (ResolvedJavaType) type);
/*
* When an argument is a Word type, we can have a mismatch of primitive/object types
* here. Not inserting a PiNode is a safe fallback, and Word types need no additional
* type information anyway.
*/
if (targetType != null && !targetType.getType().isPrimitive() && !argument.getStackKind().isPrimitive()) {
ResolvedJavaType argumentType = StampTool.typeOrNull(argument.stamp(NodeView.DEFAULT));
if (argumentType == null || (argumentType.isAssignableFrom(targetType.getType()) && !argumentType.equals(targetType.getType()))) {
LogicNode inst = InstanceOfNode.createAllowNull(targetType, argument, null, null);
assert !inst.isAlive();
if (!inst.isTautology()) {
inst = adder.add(inst);
AnchoringNode guardAnchor = adder.getGuardAnchor();
DeoptimizationReason reason = DeoptimizationReason.ClassCastException;
DeoptimizationAction action = DeoptimizationAction.InvalidateRecompile;
JavaConstant speculation = JavaConstant.NULL_POINTER;
GuardingNode guard;
if (guardAnchor == null) {
FixedGuardNode fixedGuard = adder.add(new FixedGuardNode(inst, reason, action, speculation, false));
guard = fixedGuard;
} else {
GuardNode newGuard = adder.add(new GuardNode(inst, guardAnchor, reason, action, false, speculation));
adder.add(new ValueAnchorNode(newGuard));
guard = newGuard;
}
ValueNode valueNode = adder.add(PiNode.create(argument, StampFactory.object(targetType), guard.asNode()));
arguments[index] = valueNode;
}
}
}
}
}
use of org.graalvm.compiler.nodes.extended.ValueAnchorNode in project graal by oracle.
the class ConditionAnchorNode method lower.
@Override
public void lower(LoweringTool tool) {
if (graph().getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) {
ValueAnchorNode newAnchor = graph().add(new ValueAnchorNode(null));
graph().replaceFixedWithFixed(this, newAnchor);
}
}
use of org.graalvm.compiler.nodes.extended.ValueAnchorNode in project graal by oracle.
the class DevirtualizeCallsPhase method singleCallee.
private static void singleCallee(HostedMethod singleCallee, StructuredGraph graph, Invoke invoke, SubstrateMethodCallTargetNode callTarget) {
/*
* The invoke has only one callee, i.e., the call can be devirtualized to this callee. This
* allows later inlining of the callee.
*
* We have to be careful to guard the improvement of the receiver type that is implied by
* the devirtualization: The callee assumes that the receiver type is the type that declares
* the callee. While this is true for all parts of the callee, it does not necessarily hold
* for all parts of the caller. So we need to ensure that after a possible inlining no parts
* of the callee float out to parts of the caller where the receiver type assumption does
* not hold. Since we do not know where in the caller a possible type check is performed, we
* anchor the receiver to the place of the original invoke.
*/
ValueAnchorNode anchor = graph.add(new ValueAnchorNode(null));
graph.addBeforeFixed(invoke.asNode(), anchor);
Stamp anchoredReceiverStamp = StampFactory.object(TypeReference.createWithoutAssumptions(singleCallee.getDeclaringClass()));
ValueNode anchoredReceiver = graph.unique(new PiNode(invoke.getReceiver(), anchoredReceiverStamp, anchor));
invoke.callTarget().replaceFirstInput(invoke.getReceiver(), anchoredReceiver);
assert callTarget.invokeKind() == InvokeKind.Virtual || callTarget.invokeKind() == InvokeKind.Interface;
callTarget.setInvokeKind(InvokeKind.Special);
callTarget.setTargetMethod(singleCallee);
}
use of org.graalvm.compiler.nodes.extended.ValueAnchorNode in project graal by oracle.
the class LoopEx method detectCounted.
public boolean detectCounted() {
LoopBeginNode loopBegin = loopBegin();
FixedNode next = loopBegin.next();
while (next instanceof FixedGuardNode || next instanceof ValueAnchorNode || next instanceof FullInfopointNode) {
next = ((FixedWithNextNode) next).next();
}
if (next instanceof IfNode) {
IfNode ifNode = (IfNode) next;
boolean negated = false;
if (!loopBegin.isLoopExit(ifNode.falseSuccessor())) {
if (!loopBegin.isLoopExit(ifNode.trueSuccessor())) {
return false;
}
negated = true;
}
LogicNode ifTest = ifNode.condition();
if (!(ifTest instanceof IntegerLessThanNode) && !(ifTest instanceof IntegerEqualsNode)) {
if (ifTest instanceof IntegerBelowNode) {
ifTest.getDebug().log("Ignored potential Counted loop at %s with |<|", loopBegin);
}
return false;
}
CompareNode lessThan = (CompareNode) ifTest;
Condition condition = null;
InductionVariable iv = null;
ValueNode limit = null;
if (isOutsideLoop(lessThan.getX())) {
iv = getInductionVariables().get(lessThan.getY());
if (iv != null) {
condition = lessThan.condition().asCondition().mirror();
limit = lessThan.getX();
}
} else if (isOutsideLoop(lessThan.getY())) {
iv = getInductionVariables().get(lessThan.getX());
if (iv != null) {
condition = lessThan.condition().asCondition();
limit = lessThan.getY();
}
}
if (condition == null) {
return false;
}
if (negated) {
condition = condition.negate();
}
boolean oneOff = false;
switch(condition) {
case EQ:
return false;
case NE:
{
if (!iv.isConstantStride() || Math.abs(iv.constantStride()) != 1) {
return false;
}
IntegerStamp initStamp = (IntegerStamp) iv.initNode().stamp(NodeView.DEFAULT);
IntegerStamp limitStamp = (IntegerStamp) limit.stamp(NodeView.DEFAULT);
if (iv.direction() == Direction.Up) {
if (initStamp.upperBound() > limitStamp.lowerBound()) {
return false;
}
} else if (iv.direction() == Direction.Down) {
if (initStamp.lowerBound() < limitStamp.upperBound()) {
return false;
}
} else {
return false;
}
break;
}
case LE:
oneOff = true;
if (iv.direction() != Direction.Up) {
return false;
}
break;
case LT:
if (iv.direction() != Direction.Up) {
return false;
}
break;
case GE:
oneOff = true;
if (iv.direction() != Direction.Down) {
return false;
}
break;
case GT:
if (iv.direction() != Direction.Down) {
return false;
}
break;
default:
throw GraalError.shouldNotReachHere();
}
counted = new CountedLoopInfo(this, iv, ifNode, limit, oneOff, negated ? ifNode.falseSuccessor() : ifNode.trueSuccessor());
return true;
}
return false;
}
use of org.graalvm.compiler.nodes.extended.ValueAnchorNode in project graal by oracle.
the class MethodCallTargetNode method tryCheckCastSingleImplementor.
private boolean tryCheckCastSingleImplementor(ValueNode receiver, TypeReference speculatedType) {
ResolvedJavaType singleImplementor = speculatedType.getType();
if (singleImplementor != null) {
ResolvedJavaMethod singleImplementorMethod = singleImplementor.resolveConcreteMethod(targetMethod(), invoke().getContextType());
if (singleImplementorMethod != null) {
/**
* We have an invoke on an interface with a single implementor. We can replace this
* with an invoke virtual.
*
* To do so we need to ensure two properties: 1) the receiver must implement the
* interface (declaredReceiverType). The verifier does not prove this so we need a
* dynamic check. 2) we need to ensure that there is still only one implementor of
* this interface, i.e. that we are calling the right method. We could do this with
* 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.
*/
ValueAnchorNode anchor = new ValueAnchorNode(null);
if (anchor != null) {
graph().add(anchor);
graph().addBeforeFixed(invoke().asNode(), anchor);
}
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);
if (speculatedType.isExact()) {
setInvokeKind(InvokeKind.Special);
} else {
setInvokeKind(InvokeKind.Virtual);
}
setTargetMethod(singleImplementorMethod);
return true;
}
}
return false;
}
Aggregations