use of org.graalvm.compiler.nodes.GraphDecoder.ProxyPlaceholder in project graal by oracle.
the class LoopDetector method handleLoopExplosionBegin.
protected void handleLoopExplosionBegin(MethodScope methodScope, LoopScope loopScope, LoopBeginNode loopBegin) {
checkLoopExplosionIteration(methodScope, loopScope);
List<EndNode> predecessors = loopBegin.forwardEnds().snapshot();
FixedNode successor = loopBegin.next();
FrameState frameState = loopBegin.stateAfter();
if (methodScope.loopExplosion == LoopExplosionKind.MERGE_EXPLODE) {
LoopExplosionState queryState = new LoopExplosionState(frameState, null);
LoopExplosionState existingState = loopScope.iterationStates.get(queryState);
if (existingState != null) {
loopBegin.replaceAtUsagesAndDelete(existingState.merge);
successor.safeDelete();
for (EndNode predecessor : predecessors) {
existingState.merge.addForwardEnd(predecessor);
}
return;
}
}
MergeNode merge = graph.add(new MergeNode());
methodScope.loopExplosionMerges.add(merge);
if (methodScope.loopExplosion == LoopExplosionKind.MERGE_EXPLODE) {
if (loopScope.iterationStates.size() == 0 && loopScope.loopDepth == 1) {
if (methodScope.loopExplosionHead != null) {
throw new PermanentBailoutException("Graal implementation restriction: Method with %s loop explosion must not have more than one top-level loop", LoopExplosionKind.MERGE_EXPLODE);
}
methodScope.loopExplosionHead = merge;
}
List<ValueNode> newFrameStateValues = new ArrayList<>();
for (ValueNode frameStateValue : frameState.values) {
if (frameStateValue == null || frameStateValue.isConstant() || !graph.isNew(methodScope.methodStartMark, frameStateValue)) {
newFrameStateValues.add(frameStateValue);
} else {
ProxyPlaceholder newFrameStateValue = graph.unique(new ProxyPlaceholder(frameStateValue, merge));
newFrameStateValues.add(newFrameStateValue);
/*
* We do not have the orderID of the value anymore, so we need to search through
* the complete list of nodes to find a match.
*/
for (int i = 0; i < loopScope.createdNodes.length; i++) {
if (loopScope.createdNodes[i] == frameStateValue) {
loopScope.createdNodes[i] = newFrameStateValue;
}
}
if (loopScope.initialCreatedNodes != null) {
for (int i = 0; i < loopScope.initialCreatedNodes.length; i++) {
if (loopScope.initialCreatedNodes[i] == frameStateValue) {
loopScope.initialCreatedNodes[i] = newFrameStateValue;
}
}
}
}
}
FrameState newFrameState = graph.add(new FrameState(frameState.outerFrameState(), frameState.getCode(), frameState.bci, newFrameStateValues, frameState.localsSize(), frameState.stackSize(), frameState.rethrowException(), frameState.duringCall(), frameState.monitorIds(), frameState.virtualObjectMappings()));
frameState.replaceAtUsagesAndDelete(newFrameState);
frameState = newFrameState;
}
loopBegin.replaceAtUsagesAndDelete(merge);
merge.setStateAfter(frameState);
merge.setNext(successor);
for (EndNode predecessor : predecessors) {
merge.addForwardEnd(predecessor);
}
if (methodScope.loopExplosion == LoopExplosionKind.MERGE_EXPLODE) {
LoopExplosionState explosionState = new LoopExplosionState(frameState, merge);
loopScope.iterationStates.put(explosionState, explosionState);
}
}
use of org.graalvm.compiler.nodes.GraphDecoder.ProxyPlaceholder in project graal by oracle.
the class LoopDetector method handleLoopExplosionProxyNodes.
protected void handleLoopExplosionProxyNodes(MethodScope methodScope, LoopScope loopScope, LoopScope outerScope, LoopExitNode loopExit, int loopExitOrderId) {
assert loopExit.stateAfter() == null;
int stateAfterOrderId = readOrderId(methodScope);
BeginNode begin = graph.add(new BeginNode());
FixedNode loopExitSuccessor = loopExit.next();
loopExit.replaceAtPredecessor(begin);
MergeNode loopExitPlaceholder = null;
if (methodScope.loopExplosion == LoopExplosionKind.MERGE_EXPLODE && loopScope.loopDepth == 1) {
/*
* This exit might end up as a loop exit of a loop detected after partial evaluation. We
* need to be able to create a FrameState and the necessary proxy nodes in this case.
*/
loopExitPlaceholder = graph.add(new MergeNode());
methodScope.loopExplosionMerges.add(loopExitPlaceholder);
EndNode end = graph.add(new EndNode());
begin.setNext(end);
loopExitPlaceholder.addForwardEnd(end);
begin = graph.add(new BeginNode());
loopExitPlaceholder.setNext(begin);
}
/*
* In the original graph, the loop exit is not a merge node. Multiple exploded loop
* iterations now take the same loop exit, so we have to introduce a new merge node to
* handle the merge.
*/
MergeNode merge = null;
Node existingExit = lookupNode(outerScope, loopExitOrderId);
if (existingExit == null) {
/* First loop iteration that exits. No merge necessary yet. */
registerNode(outerScope, loopExitOrderId, begin, false, false);
begin.setNext(loopExitSuccessor);
} else if (existingExit instanceof BeginNode) {
/* Second loop iteration that exits. Create the merge. */
merge = graph.add(new MergeNode());
registerNode(outerScope, loopExitOrderId, merge, true, false);
/* Add the first iteration. */
EndNode firstEnd = graph.add(new EndNode());
((BeginNode) existingExit).setNext(firstEnd);
merge.addForwardEnd(firstEnd);
merge.setNext(loopExitSuccessor);
} else {
/* Subsequent loop iteration. Merge already created. */
merge = (MergeNode) existingExit;
}
if (merge != null) {
EndNode end = graph.add(new EndNode());
begin.setNext(end);
merge.addForwardEnd(end);
}
/*
* Possibly create phi nodes for the original proxy nodes that flow out of the loop. Note
* that we definitely do not need a proxy node itself anymore, since the loop was exploded
* and is no longer present.
*/
int numProxies = methodScope.reader.getUVInt();
boolean phiCreated = false;
for (int i = 0; i < numProxies; i++) {
int proxyOrderId = readOrderId(methodScope);
ProxyNode proxy = (ProxyNode) ensureNodeCreated(methodScope, loopScope, proxyOrderId);
ValueNode phiInput = proxy.value();
if (loopExitPlaceholder != null) {
if (!phiInput.isConstant()) {
phiInput = graph.unique(new ProxyPlaceholder(phiInput, loopExitPlaceholder));
}
registerNode(loopScope, proxyOrderId, phiInput, true, false);
}
ValueNode replacement;
ValueNode existing = (ValueNode) outerScope.createdNodes[proxyOrderId];
if (existing == null || existing == phiInput) {
/*
* We are at the first loop exit, or the proxy carries the same value for all exits.
* We do not need a phi node yet.
*/
registerNode(outerScope, proxyOrderId, phiInput, true, false);
replacement = phiInput;
} else if (!merge.isPhiAtMerge(existing)) {
/* Now we have two different values, so we need to create a phi node. */
PhiNode phi;
if (proxy instanceof ValueProxyNode) {
phi = graph.addWithoutUnique(new ValuePhiNode(proxy.stamp(NodeView.DEFAULT), merge));
} else if (proxy instanceof GuardProxyNode) {
phi = graph.addWithoutUnique(new GuardPhiNode(merge));
} else {
throw GraalError.shouldNotReachHere();
}
/* Add the inputs from all previous exits. */
for (int j = 0; j < merge.phiPredecessorCount() - 1; j++) {
phi.addInput(existing);
}
/* Add the input from this exit. */
phi.addInput(phiInput);
registerNode(outerScope, proxyOrderId, phi, true, false);
replacement = phi;
phiCreated = true;
} else {
/* Phi node has been created before, so just add the new input. */
PhiNode phi = (PhiNode) existing;
phi.addInput(phiInput);
replacement = phi;
}
proxy.replaceAtUsagesAndDelete(replacement);
}
if (loopExitPlaceholder != null) {
registerNode(loopScope, stateAfterOrderId, null, true, true);
loopExitPlaceholder.setStateAfter((FrameState) ensureNodeCreated(methodScope, loopScope, stateAfterOrderId));
}
if (merge != null && (merge.stateAfter() == null || phiCreated)) {
FrameState oldStateAfter = merge.stateAfter();
registerNode(outerScope, stateAfterOrderId, null, true, true);
merge.setStateAfter((FrameState) ensureNodeCreated(methodScope, outerScope, stateAfterOrderId));
if (oldStateAfter != null) {
oldStateAfter.safeDelete();
}
}
loopExit.safeDelete();
assert loopExitSuccessor.predecessor() == null;
if (merge != null) {
merge.getNodeClass().getSuccessorEdges().update(merge, null, loopExitSuccessor);
} else {
begin.getNodeClass().getSuccessorEdges().update(begin, null, loopExitSuccessor);
}
}
use of org.graalvm.compiler.nodes.GraphDecoder.ProxyPlaceholder in project graal by oracle.
the class LoopDetector method assignLoopExitState.
/**
* During graph decoding, we create a FrameState for every exploded loop iteration. This is
* mostly the state that we want, we only need to tweak it a little bit: we need to insert the
* appropriate ProxyNodes for all values that are created inside the loop and that flow out of
* the loop.
*/
private void assignLoopExitState(LoopExitNode loopExit, AbstractMergeNode loopExplosionMerge, AbstractEndNode loopExplosionEnd) {
FrameState oldState = loopExplosionMerge.stateAfter();
/* Collect all nodes that are in the FrameState at the LoopBegin. */
EconomicSet<Node> loopBeginValues = EconomicSet.create(Equivalence.IDENTITY);
for (FrameState state = loopExit.loopBegin().stateAfter(); state != null; state = state.outerFrameState()) {
for (ValueNode value : state.values()) {
if (value != null && !value.isConstant() && !loopExit.loopBegin().isPhiAtMerge(value)) {
loopBeginValues.add(ProxyPlaceholder.unwrap(value));
}
}
}
List<ValueNode> newValues = new ArrayList<>(oldState.values().size());
for (ValueNode v : oldState.values()) {
ValueNode value = v;
ValueNode realValue = ProxyPlaceholder.unwrap(value);
/*
* The LoopExit is inserted before the existing merge, i.e., separately for every branch
* that leads to the merge. So for phi functions of the merge, we need to take the input
* that corresponds to our branch.
*/
if (realValue instanceof PhiNode && loopExplosionMerge.isPhiAtMerge(realValue)) {
value = ((PhiNode) realValue).valueAt(loopExplosionEnd);
realValue = ProxyPlaceholder.unwrap(value);
}
if (realValue == null || realValue.isConstant() || loopBeginValues.contains(realValue) || !graph.isNew(methodScope.methodStartMark, realValue)) {
newValues.add(realValue);
} else {
/*
* The node is not in the FrameState of the LoopBegin, i.e., it is a value computed
* inside the loop.
*/
GraalError.guarantee(value instanceof ProxyPlaceholder && ((ProxyPlaceholder) value).proxyPoint == loopExplosionMerge, "Value flowing out of loop, but we are not prepared to insert a ProxyNode");
ProxyPlaceholder proxyPlaceholder = (ProxyPlaceholder) value;
ValueProxyNode proxy = ProxyNode.forValue(proxyPlaceholder.value, loopExit, graph);
proxyPlaceholder.setValue(proxy);
newValues.add(proxy);
}
}
FrameState newState = new FrameState(oldState.outerFrameState(), oldState.getCode(), oldState.bci, newValues, oldState.localsSize(), oldState.stackSize(), oldState.rethrowException(), oldState.duringCall(), oldState.monitorIds(), oldState.virtualObjectMappings());
assert loopExit.stateAfter() == null;
loopExit.setStateAfter(graph.add(newState));
}
Aggregations