use of org.graalvm.compiler.nodes.AbstractMergeNode in project graal by oracle.
the class JNIJavaCallWrapperMethod method buildGraph.
@Override
public StructuredGraph buildGraph(DebugContext debug, ResolvedJavaMethod method, HostedProviders providers, Purpose purpose) {
UniverseMetaAccess metaAccess = (UniverseMetaAccess) providers.getMetaAccess();
JNIGraphKit kit = new JNIGraphKit(debug, providers, method);
StructuredGraph graph = kit.getGraph();
FrameStateBuilder state = new FrameStateBuilder(null, method, graph);
state.initializeForMethodStart(null, true, providers.getGraphBuilderPlugins());
JavaKind vmThreadKind = metaAccess.lookupJavaType(JNIEnvironment.class).getJavaKind();
ValueNode vmThread = kit.loadLocal(0, vmThreadKind);
kit.append(new CEntryPointEnterNode(EnterAction.Enter, vmThread));
ResolvedJavaMethod invokeMethod = providers.getMetaAccess().lookupJavaMethod(reflectMethod);
Signature invokeSignature = invokeMethod.getSignature();
List<Pair<ValueNode, ResolvedJavaType>> argsWithTypes = loadAndUnboxArguments(kit, providers, invokeMethod, invokeSignature);
JavaKind returnKind = invokeSignature.getReturnKind();
if (invokeMethod.isConstructor()) {
// return `this` to implement NewObject
assert returnKind == JavaKind.Void;
returnKind = JavaKind.Object;
}
IfNode ifNode = kit.startIf(null, BranchProbabilityNode.FAST_PATH_PROBABILITY);
kit.thenPart();
LogicNode typeChecks = LogicConstantNode.tautology(kit.getGraph());
ValueNode[] args = new ValueNode[argsWithTypes.size()];
for (int i = 0; i < argsWithTypes.size(); i++) {
ValueNode value = argsWithTypes.get(i).getLeft();
ResolvedJavaType type = argsWithTypes.get(i).getRight();
if (!type.isPrimitive() && !type.isJavaLangObject()) {
TypeReference typeRef = TypeReference.createTrusted(kit.getAssumptions(), type);
LogicNode instanceOf = kit.unique(InstanceOfNode.createAllowNull(typeRef, value, null, null));
typeChecks = LogicNode.and(typeChecks, instanceOf, BranchProbabilityNode.FAST_PATH_PROBABILITY);
FixedGuardNode guard = kit.append(new FixedGuardNode(instanceOf, DeoptimizationReason.ClassCastException, DeoptimizationAction.None, false));
value = kit.append(PiNode.create(value, StampFactory.object(typeRef), guard));
}
args[i] = value;
}
// safe because logic nodes are floating
ifNode.setCondition(typeChecks);
InvokeKind kind = //
invokeMethod.isStatic() ? //
InvokeKind.Static : ((nonVirtual || invokeMethod.isConstructor()) ? InvokeKind.Special : InvokeKind.Virtual);
ValueNode invokeResult = createInvoke(kit, invokeMethod, kind, state, kit.bci(), args);
if (invokeMethod.isConstructor()) {
// return `this` to implement NewObject
invokeResult = args[0];
}
// illegal parameter types
kit.elsePart();
ConstantNode exceptionObject = kit.createObject(cachedArgumentClassCastException);
kit.retainPendingException(exceptionObject);
ValueNode typeMismatchValue = null;
if (returnKind != JavaKind.Void) {
typeMismatchValue = kit.unique(ConstantNode.defaultForKind(returnKind.getStackKind()));
}
AbstractMergeNode merge = kit.endIf();
ValueNode returnValue = null;
if (returnKind != JavaKind.Void) {
ValueNode[] inputs = { invokeResult, typeMismatchValue };
returnValue = kit.getGraph().addWithoutUnique(new ValuePhiNode(invokeResult.stamp(NodeView.DEFAULT), merge, inputs));
state.push(returnKind, returnValue);
}
merge.setStateAfter(state.create(kit.bci(), merge));
if (returnKind != JavaKind.Void) {
state.pop(returnKind);
if (returnKind.isObject()) {
returnValue = kit.boxObjectInLocalHandle(returnValue);
}
}
kit.append(new CEntryPointLeaveNode(LeaveAction.Leave));
kit.createReturn(returnValue, returnKind);
assert graph.verify();
return graph;
}
use of org.graalvm.compiler.nodes.AbstractMergeNode in project graal by oracle.
the class JNIJavaCallWrapperMethod method createInvoke.
private static ValueNode createInvoke(JNIGraphKit kit, ResolvedJavaMethod invokeMethod, InvokeKind kind, FrameStateBuilder state, int bci, ValueNode... args) {
int exceptionEdgeBci = kit.bci();
InvokeWithExceptionNode invoke = kit.startInvokeWithException(invokeMethod, kind, state, bci, exceptionEdgeBci, args);
kit.exceptionPart();
ExceptionObjectNode exceptionObject = kit.exceptionObject();
kit.retainPendingException(exceptionObject);
ValueNode exceptionValue = null;
if (invoke.getStackKind() != JavaKind.Void) {
exceptionValue = kit.unique(ConstantNode.defaultForKind(invoke.getStackKind()));
}
AbstractMergeNode merge = kit.endInvokeWithException();
ValueNode returnValue = null;
JavaKind returnKind = invokeMethod.getSignature().getReturnKind();
if (invoke.getStackKind() != JavaKind.Void) {
ValueNode[] inputs = { invoke, exceptionValue };
returnValue = kit.getGraph().addWithoutUnique(new ValuePhiNode(invoke.stamp(NodeView.DEFAULT), merge, inputs));
state.push(returnKind, returnValue);
}
merge.setStateAfter(state.create(bci, merge));
if (invoke.getStackKind() != JavaKind.Void) {
state.pop(returnKind);
}
return returnValue;
}
use of org.graalvm.compiler.nodes.AbstractMergeNode in project graal by oracle.
the class JNIPrimitiveArrayOperationMethod method newArray.
private ValueNode newArray(HostedProviders providers, JNIGraphKit kit, List<ValueNode> arguments) {
ResolvedJavaType elementType = providers.getMetaAccess().lookupJavaType(elementKind.toJavaClass());
ValueNode length = arguments.get(1);
ConstantNode zero = kit.createInt(0);
kit.startIf(new IntegerLessThanNode(length, zero), BranchProbabilityNode.VERY_SLOW_PATH_PROBABILITY);
kit.thenPart();
ValueNode nullHandle = kit.createConstant(JavaConstant.INT_0, providers.getWordTypes().getWordKind());
kit.elsePart();
ValueNode array = kit.append(new NewArrayNode(elementType, length, true));
ValueNode arrayHandle = kit.boxObjectInLocalHandle(array);
AbstractMergeNode merge = kit.endIf();
Stamp handleStamp = providers.getWordTypes().getWordStamp(providers.getMetaAccess().lookupJavaType(JNIObjectHandle.class));
return kit.unique(new ValuePhiNode(handleStamp, merge, new ValueNode[] { nullHandle, arrayHandle }));
}
use of org.graalvm.compiler.nodes.AbstractMergeNode in project graal by oracle.
the class LoopFragment method computeNodes.
protected static void computeNodes(NodeBitMap nodes, Graph graph, Iterable<AbstractBeginNode> blocks, Iterable<AbstractBeginNode> earlyExits) {
for (AbstractBeginNode b : blocks) {
if (b.isDeleted()) {
continue;
}
for (Node n : b.getBlockNodes()) {
if (n instanceof Invoke) {
nodes.mark(((Invoke) n).callTarget());
}
if (n instanceof NodeWithState) {
NodeWithState withState = (NodeWithState) n;
withState.states().forEach(state -> state.applyToVirtual(node -> nodes.mark(node)));
}
if (n instanceof AbstractMergeNode) {
// if a merge is in the loop, all of its phis are also in the loop
for (PhiNode phi : ((AbstractMergeNode) n).phis()) {
nodes.mark(phi);
}
}
nodes.mark(n);
}
}
for (AbstractBeginNode earlyExit : earlyExits) {
if (earlyExit.isDeleted()) {
continue;
}
nodes.mark(earlyExit);
if (earlyExit instanceof LoopExitNode) {
LoopExitNode loopExit = (LoopExitNode) earlyExit;
FrameState stateAfter = loopExit.stateAfter();
if (stateAfter != null) {
stateAfter.applyToVirtual(node -> nodes.mark(node));
}
for (ProxyNode proxy : loopExit.proxies()) {
nodes.mark(proxy);
}
}
}
final NodeBitMap nonLoopNodes = graph.createNodeBitMap();
Deque<WorkListEntry> worklist = new ArrayDeque<>();
for (AbstractBeginNode b : blocks) {
if (b.isDeleted()) {
continue;
}
for (Node n : b.getBlockNodes()) {
if (n instanceof CommitAllocationNode) {
for (VirtualObjectNode obj : ((CommitAllocationNode) n).getVirtualObjects()) {
markFloating(worklist, obj, nodes, nonLoopNodes);
}
}
if (n instanceof MonitorEnterNode) {
markFloating(worklist, ((MonitorEnterNode) n).getMonitorId(), nodes, nonLoopNodes);
}
if (n instanceof AbstractMergeNode) {
/*
* Since we already marked all phi nodes as being in the loop to break cycles,
* we also have to iterate over their usages here.
*/
for (PhiNode phi : ((AbstractMergeNode) n).phis()) {
for (Node usage : phi.usages()) {
markFloating(worklist, usage, nodes, nonLoopNodes);
}
}
}
for (Node usage : n.usages()) {
markFloating(worklist, usage, nodes, nonLoopNodes);
}
}
}
}
use of org.graalvm.compiler.nodes.AbstractMergeNode in project graal by oracle.
the class LoopFragmentInside method mergeEnds.
private AbstractBeginNode mergeEnds() {
assert isDuplicate();
List<EndNode> endsToMerge = new LinkedList<>();
// map peel exits to the corresponding loop exits
EconomicMap<AbstractEndNode, LoopEndNode> reverseEnds = EconomicMap.create(Equivalence.IDENTITY);
LoopBeginNode loopBegin = original().loop().loopBegin();
for (LoopEndNode le : loopBegin.loopEnds()) {
AbstractEndNode duplicate = getDuplicatedNode(le);
if (duplicate != null) {
endsToMerge.add((EndNode) duplicate);
reverseEnds.put(duplicate, le);
}
}
mergedInitializers = EconomicMap.create(Equivalence.IDENTITY);
AbstractBeginNode newExit;
StructuredGraph graph = graph();
if (endsToMerge.size() == 1) {
AbstractEndNode end = endsToMerge.get(0);
assert end.hasNoUsages();
newExit = graph.add(new BeginNode());
end.replaceAtPredecessor(newExit);
end.safeDelete();
} else {
assert endsToMerge.size() > 1;
AbstractMergeNode newExitMerge = graph.add(new MergeNode());
newExit = newExitMerge;
FrameState state = loopBegin.stateAfter();
FrameState duplicateState = null;
if (state != null) {
duplicateState = state.duplicateWithVirtualState();
newExitMerge.setStateAfter(duplicateState);
}
for (EndNode end : endsToMerge) {
newExitMerge.addForwardEnd(end);
}
for (final PhiNode phi : loopBegin.phis().snapshot()) {
if (phi.hasNoUsages()) {
continue;
}
final PhiNode firstPhi = patchPhi(graph, phi, newExitMerge);
for (AbstractEndNode end : newExitMerge.forwardEnds()) {
LoopEndNode loopEnd = reverseEnds.get(end);
ValueNode prim = prim(phi.valueAt(loopEnd));
assert prim != null;
firstPhi.addInput(prim);
}
ValueNode initializer = firstPhi;
if (duplicateState != null) {
// fix the merge's state after
duplicateState.applyToNonVirtual(new NodeClosure<ValueNode>() {
@Override
public void apply(Node from, ValueNode node) {
if (node == phi) {
from.replaceFirstInput(phi, firstPhi);
}
}
});
}
mergedInitializers.put(phi, initializer);
}
}
return newExit;
}
Aggregations