use of org.graalvm.compiler.nodes.BeginNode in project graal by oracle.
the class GraphKit method startIf.
/**
* Starts an if-block. This call can be followed by a call to {@link #thenPart} to start
* emitting the code executed when the condition hold; and a call to {@link #elsePart} to start
* emititng the code when the condition does not hold. It must be followed by a call to
* {@link #endIf} to close the if-block.
*
* @param condition The condition for the if-block
* @param trueProbability The estimated probability the condition is true
* @return the created {@link IfNode}.
*/
public IfNode startIf(LogicNode condition, double trueProbability) {
AbstractBeginNode thenSuccessor = graph.add(new BeginNode());
AbstractBeginNode elseSuccessor = graph.add(new BeginNode());
IfNode node = append(new IfNode(condition, thenSuccessor, elseSuccessor, trueProbability));
lastFixedNode = null;
IfStructure s = new IfStructure();
s.state = IfState.CONDITION;
s.thenPart = thenSuccessor;
s.elsePart = elseSuccessor;
pushStructure(s);
return node;
}
use of org.graalvm.compiler.nodes.BeginNode in project graal by oracle.
the class IntegerExactArithmeticSplitNode method lower.
static void lower(LoweringTool tool, IntegerExactArithmeticNode node) {
if (node.asNode().graph().getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) {
FloatingNode floatingNode = (FloatingNode) node;
FixedWithNextNode previous = tool.lastFixedNode();
FixedNode next = previous.next();
previous.setNext(null);
DeoptimizeNode deopt = floatingNode.graph().add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.ArithmeticException));
AbstractBeginNode normalBegin = floatingNode.graph().add(new BeginNode());
normalBegin.setNext(next);
IntegerExactArithmeticSplitNode split = node.createSplit(normalBegin, BeginNode.begin(deopt));
previous.setNext(split);
floatingNode.replaceAndDelete(split);
}
}
use of org.graalvm.compiler.nodes.BeginNode in project graal by oracle.
the class BytecodeParser method guardIntrinsic.
/**
* Weaves a test of the receiver type to ensure the dispatch will select {@code targetMethod}
* and not another method that overrides it. This should only be called if there is an intrinsic
* (i.e., an {@link InvocationPlugin}) for {@code targetMethod} and the invocation is indirect.
*
* The control flow woven around the intrinsic is as follows:
*
* <pre>
* if (LoadMethod(LoadHub(receiver)) == targetMethod) {
* <intrinsic for targetMethod>
* } else {
* <virtual call to targetMethod>
* }
* </pre>
*
* The {@code else} branch is woven by {@link #afterInvocationPluginExecution}.
*
* @return {@code null} if the intrinsic cannot be used otherwise an object to be used by
* {@link #afterInvocationPluginExecution} to weave code for the non-intrinsic branch
*/
protected IntrinsicGuard guardIntrinsic(ValueNode[] args, ResolvedJavaMethod targetMethod, InvocationPluginReceiver pluginReceiver) {
ValueNode intrinsicReceiver = args[0];
ResolvedJavaType receiverType = StampTool.typeOrNull(intrinsicReceiver);
if (receiverType == null) {
// The verifier guarantees it to be at least type declaring targetMethod
receiverType = targetMethod.getDeclaringClass();
}
ResolvedJavaMethod resolvedMethod = receiverType.resolveMethod(targetMethod, method.getDeclaringClass());
if (resolvedMethod == null || resolvedMethod.equals(targetMethod)) {
assert resolvedMethod == null || targetMethod.getDeclaringClass().isAssignableFrom(resolvedMethod.getDeclaringClass());
Mark mark = graph.getMark();
FixedWithNextNode currentLastInstr = lastInstr;
ValueNode nonNullReceiver = pluginReceiver.get();
Stamp methodStamp = stampProvider.createMethodStamp();
LoadHubNode hub = graph.unique(new LoadHubNode(stampProvider, nonNullReceiver));
LoadMethodNode actual = append(new LoadMethodNode(methodStamp, targetMethod, receiverType, method.getDeclaringClass(), hub));
ConstantNode expected = graph.unique(ConstantNode.forConstant(methodStamp, targetMethod.getEncoding(), getMetaAccess()));
LogicNode compare = graph.addOrUniqueWithInputs(CompareNode.createCompareNode(constantReflection, metaAccess, options, null, CanonicalCondition.EQ, actual, expected, NodeView.DEFAULT));
JavaTypeProfile profile = null;
if (profilingInfo != null && this.optimisticOpts.useTypeCheckHints(getOptions())) {
profile = profilingInfo.getTypeProfile(bci());
if (profile != null) {
JavaTypeProfile newProfile = adjustProfileForInvocationPlugin(profile, targetMethod);
if (newProfile != profile) {
if (newProfile.getTypes().length == 0) {
// All profiled types select the intrinsic so
// emit a fixed guard instead of an if-then-else.
lastInstr = append(new FixedGuardNode(compare, TypeCheckedInliningViolated, InvalidateReprofile, false));
return new IntrinsicGuard(currentLastInstr, intrinsicReceiver, mark, null, null);
}
} else {
// No profiled types select the intrinsic so emit a virtual call
return null;
}
profile = newProfile;
}
}
AbstractBeginNode intrinsicBranch = graph.add(new BeginNode());
AbstractBeginNode nonIntrinsicBranch = graph.add(new BeginNode());
append(new IfNode(compare, intrinsicBranch, nonIntrinsicBranch, FAST_PATH_PROBABILITY));
lastInstr = intrinsicBranch;
return new IntrinsicGuard(currentLastInstr, intrinsicReceiver, mark, nonIntrinsicBranch, profile);
} else {
// Receiver selects an overriding method so emit a virtual call
return null;
}
}
use of org.graalvm.compiler.nodes.BeginNode in project graal by oracle.
the class BytecodeParser method createExceptionDispatch.
private void createExceptionDispatch(ExceptionDispatchBlock block) {
lastInstr = finishInstruction(lastInstr, frameState);
assert frameState.stackSize() == 1 : frameState;
if (block.handler.isCatchAll()) {
assert block.getSuccessorCount() == 1;
appendGoto(block.getSuccessor(0));
return;
}
JavaType catchType = block.handler.getCatchType();
if (graphBuilderConfig.eagerResolving()) {
catchType = lookupType(block.handler.catchTypeCPI(), INSTANCEOF);
}
if (catchType instanceof ResolvedJavaType) {
TypeReference checkedCatchType = TypeReference.createTrusted(graph.getAssumptions(), (ResolvedJavaType) catchType);
if (graphBuilderConfig.getSkippedExceptionTypes() != null) {
for (ResolvedJavaType skippedType : graphBuilderConfig.getSkippedExceptionTypes()) {
if (skippedType.isAssignableFrom(checkedCatchType.getType())) {
BciBlock nextBlock = block.getSuccessorCount() == 1 ? blockMap.getUnwindBlock() : block.getSuccessor(1);
ValueNode exception = frameState.stack[0];
FixedNode trueSuccessor = graph.add(new DeoptimizeNode(InvalidateReprofile, UnreachedCode));
FixedNode nextDispatch = createTarget(nextBlock, frameState);
append(new IfNode(graph.addOrUniqueWithInputs(createInstanceOf(checkedCatchType, exception)), trueSuccessor, nextDispatch, 0));
return;
}
}
}
BciBlock nextBlock = block.getSuccessorCount() == 1 ? blockMap.getUnwindBlock() : block.getSuccessor(1);
ValueNode exception = frameState.stack[0];
/* Anchor for the piNode, which must be before any LoopExit inserted by createTarget. */
BeginNode piNodeAnchor = graph.add(new BeginNode());
ObjectStamp checkedStamp = StampFactory.objectNonNull(checkedCatchType);
PiNode piNode = graph.addWithoutUnique(new PiNode(exception, checkedStamp));
frameState.pop(JavaKind.Object);
frameState.push(JavaKind.Object, piNode);
FixedNode catchSuccessor = createTarget(block.getSuccessor(0), frameState);
frameState.pop(JavaKind.Object);
frameState.push(JavaKind.Object, exception);
FixedNode nextDispatch = createTarget(nextBlock, frameState);
piNodeAnchor.setNext(catchSuccessor);
IfNode ifNode = append(new IfNode(graph.unique(createInstanceOf(checkedCatchType, exception)), piNodeAnchor, nextDispatch, 0.5));
assert ifNode.trueSuccessor() == piNodeAnchor;
piNode.setGuard(ifNode.trueSuccessor());
} else {
handleUnresolvedExceptionType(catchType);
}
}
use of org.graalvm.compiler.nodes.BeginNode in project graal by oracle.
the class BytecodeParser method createTarget.
@SuppressWarnings("try")
private FixedNode createTarget(BciBlock block, FrameStateBuilder state, boolean canReuseInstruction, boolean canReuseState) {
assert block != null && state != null;
assert !block.isExceptionEntry || state.stackSize() == 1;
try (DebugCloseable context = openNodeContext(state, block.startBci)) {
if (getFirstInstruction(block) == null) {
/*
* This is the first time we see this block as a branch target. Create and return a
* placeholder that later can be replaced with a MergeNode when we see this block
* again.
*/
FixedNode targetNode;
if (canReuseInstruction && (block.getPredecessorCount() == 1 || !controlFlowSplit) && !block.isLoopHeader && (currentBlock.loops & ~block.loops) == 0) {
setFirstInstruction(block, lastInstr);
lastInstr = null;
} else {
setFirstInstruction(block, graph.add(new BeginNode()));
}
targetNode = getFirstInstruction(block);
Target target = checkLoopExit(targetNode, block, state);
FixedNode result = target.fixed;
FrameStateBuilder currentEntryState = target.state == state ? (canReuseState ? state : state.copy()) : target.state;
setEntryState(block, currentEntryState);
currentEntryState.clearNonLiveLocals(block, liveness, true);
debug.log("createTarget %s: first visit, result: %s", block, targetNode);
return result;
}
// We already saw this block before, so we have to merge states.
if (!getEntryState(block).isCompatibleWith(state)) {
throw bailout("stacks do not match; bytecodes would not verify");
}
if (getFirstInstruction(block) instanceof LoopBeginNode) {
assert (block.isLoopHeader && currentBlock.getId() >= block.getId()) : "must be backward branch";
/*
* Backward loop edge. We need to create a special LoopEndNode and merge with the
* loop begin node created before.
*/
LoopBeginNode loopBegin = (LoopBeginNode) getFirstInstruction(block);
LoopEndNode loopEnd = graph.add(new LoopEndNode(loopBegin));
Target target = checkLoopExit(loopEnd, block, state);
FixedNode result = target.fixed;
getEntryState(block).merge(loopBegin, target.state);
debug.log("createTarget %s: merging backward branch to loop header %s, result: %s", block, loopBegin, result);
return result;
}
assert currentBlock == null || currentBlock.getId() < block.getId() : "must not be backward branch";
assert getFirstInstruction(block).next() == null : "bytecodes already parsed for block";
if (getFirstInstruction(block) instanceof AbstractBeginNode && !(getFirstInstruction(block) instanceof AbstractMergeNode)) {
/*
* This is the second time we see this block. Create the actual MergeNode and the
* End Node for the already existing edge.
*/
AbstractBeginNode beginNode = (AbstractBeginNode) getFirstInstruction(block);
// The EndNode for the already existing edge.
EndNode end = graph.add(new EndNode());
// The MergeNode that replaces the placeholder.
AbstractMergeNode mergeNode = graph.add(new MergeNode());
FixedNode next = beginNode.next();
if (beginNode.predecessor() instanceof ControlSplitNode) {
beginNode.setNext(end);
} else {
beginNode.replaceAtPredecessor(end);
beginNode.safeDelete();
}
mergeNode.addForwardEnd(end);
mergeNode.setNext(next);
setFirstInstruction(block, mergeNode);
}
AbstractMergeNode mergeNode = (AbstractMergeNode) getFirstInstruction(block);
// The EndNode for the newly merged edge.
EndNode newEnd = graph.add(new EndNode());
Target target = checkLoopExit(newEnd, block, state);
FixedNode result = target.fixed;
getEntryState(block).merge(mergeNode, target.state);
mergeNode.addForwardEnd(newEnd);
debug.log("createTarget %s: merging state, result: %s", block, result);
return result;
}
}
Aggregations