use of org.graalvm.compiler.nodes.virtual.AllocatedObjectNode in project graal by oracle.
the class EscapeAnalysisTest method testFullyUnrolledLoop.
@Test
public void testFullyUnrolledLoop() {
prepareGraph("testFullyUnrolledLoopSnippet", false);
new LoopFullUnrollPhase(new CanonicalizerPhase(), new DefaultLoopPolicies()).apply(graph, context);
new PartialEscapePhase(false, new CanonicalizerPhase(), graph.getOptions()).apply(graph, context);
Assert.assertEquals(1, returnNodes.size());
Assert.assertTrue(returnNodes.get(0).result() instanceof AllocatedObjectNode);
CommitAllocationNode commit = ((AllocatedObjectNode) returnNodes.get(0).result()).getCommit();
Assert.assertEquals(2, commit.getValues().size());
Assert.assertEquals(1, commit.getVirtualObjects().size());
Assert.assertTrue("non-cyclic data structure expected", commit.getVirtualObjects().get(0) != commit.getValues().get(0));
}
use of org.graalvm.compiler.nodes.virtual.AllocatedObjectNode in project graal by oracle.
the class DefaultJavaLoweringProvider method finishAllocatedObjects.
public void finishAllocatedObjects(LoweringTool tool, CommitAllocationNode commit, ValueNode[] allocations) {
StructuredGraph graph = commit.graph();
for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) {
FixedValueAnchorNode anchor = graph.add(new FixedValueAnchorNode(allocations[objIndex]));
allocations[objIndex] = anchor;
graph.addBeforeFixed(commit, anchor);
}
/*
* Note that the FrameState that is assigned to these MonitorEnterNodes isn't the correct
* state. It will be the state from before the allocation occurred instead of a valid state
* after the locking is performed. In practice this should be fine since these are newly
* allocated objects. The bytecodes themselves permit allocating an object, doing a
* monitorenter and then dropping all references to the object which would produce the same
* state, though that would normally produce an IllegalMonitorStateException. In HotSpot
* some form of fast path locking should always occur so the FrameState should never
* actually be used.
*/
ArrayList<MonitorEnterNode> enters = null;
for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) {
List<MonitorIdNode> locks = commit.getLocks(objIndex);
if (locks.size() > 1) {
// Ensure that the lock operations are performed in lock depth order
ArrayList<MonitorIdNode> newList = new ArrayList<>(locks);
newList.sort((a, b) -> Integer.compare(a.getLockDepth(), b.getLockDepth()));
locks = newList;
}
int lastDepth = -1;
for (MonitorIdNode monitorId : locks) {
assert lastDepth < monitorId.getLockDepth();
lastDepth = monitorId.getLockDepth();
MonitorEnterNode enter = graph.add(new MonitorEnterNode(allocations[objIndex], monitorId));
graph.addBeforeFixed(commit, enter);
if (enters == null) {
enters = new ArrayList<>();
}
enters.add(enter);
}
}
for (Node usage : commit.usages().snapshot()) {
if (usage instanceof AllocatedObjectNode) {
AllocatedObjectNode addObject = (AllocatedObjectNode) usage;
int index = commit.getVirtualObjects().indexOf(addObject.getVirtualObject());
addObject.replaceAtUsagesAndDelete(allocations[index]);
} else {
assert enters != null;
commit.replaceAtUsages(InputType.Memory, enters.get(enters.size() - 1));
}
}
if (enters != null) {
for (MonitorEnterNode enter : enters) {
enter.lower(tool);
}
}
assert commit.hasNoUsages();
insertAllocationBarrier(commit, graph);
}
use of org.graalvm.compiler.nodes.virtual.AllocatedObjectNode in project graal by oracle.
the class PartialEscapeBlockState method materializeBefore.
/**
* Materializes the given virtual object and produces the necessary effects in the effects list.
* This transitively also materializes all other virtual objects that are reachable from the
* entries.
*/
public void materializeBefore(FixedNode fixed, VirtualObjectNode virtual, GraphEffectList materializeEffects) {
PartialEscapeClosure.COUNTER_MATERIALIZATIONS.increment(fixed.getDebug());
List<AllocatedObjectNode> objects = new ArrayList<>(2);
List<ValueNode> values = new ArrayList<>(8);
List<List<MonitorIdNode>> locks = new ArrayList<>();
List<ValueNode> otherAllocations = new ArrayList<>(2);
List<Boolean> ensureVirtual = new ArrayList<>(2);
materializeWithCommit(fixed, virtual, objects, locks, values, ensureVirtual, otherAllocations);
materializeEffects.addVirtualizationDelta(-(objects.size() + otherAllocations.size()));
materializeEffects.add("materializeBefore", new Effect() {
@Override
public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) {
for (ValueNode alloc : otherAllocations) {
ValueNode otherAllocation = graph.addOrUniqueWithInputs(alloc);
if (otherAllocation instanceof FixedWithNextNode) {
graph.addBeforeFixed(fixed, (FixedWithNextNode) otherAllocation);
} else {
assert otherAllocation instanceof FloatingNode;
}
}
if (!objects.isEmpty()) {
CommitAllocationNode commit;
if (fixed.predecessor() instanceof CommitAllocationNode) {
commit = (CommitAllocationNode) fixed.predecessor();
} else {
commit = graph.add(new CommitAllocationNode());
graph.addBeforeFixed(fixed, commit);
}
for (AllocatedObjectNode obj : objects) {
graph.addWithoutUnique(obj);
commit.getVirtualObjects().add(obj.getVirtualObject());
obj.setCommit(commit);
}
for (ValueNode value : values) {
commit.getValues().add(graph.addOrUniqueWithInputs(value));
}
for (List<MonitorIdNode> monitorIds : locks) {
commit.addLocks(monitorIds);
}
commit.getEnsureVirtual().addAll(ensureVirtual);
assert commit.usages().filter(AllocatedObjectNode.class).count() == commit.getUsageCount();
List<AllocatedObjectNode> materializedValues = commit.usages().filter(AllocatedObjectNode.class).snapshot();
for (int i = 0; i < commit.getValues().size(); i++) {
if (materializedValues.contains(commit.getValues().get(i))) {
commit.getValues().set(i, ((AllocatedObjectNode) commit.getValues().get(i)).getVirtualObject());
}
}
}
}
});
}
use of org.graalvm.compiler.nodes.virtual.AllocatedObjectNode in project graal by oracle.
the class PartialEscapeBlockState method materializeWithCommit.
private void materializeWithCommit(FixedNode fixed, VirtualObjectNode virtual, List<AllocatedObjectNode> objects, List<List<MonitorIdNode>> locks, List<ValueNode> values, List<Boolean> ensureVirtual, List<ValueNode> otherAllocations) {
ObjectState obj = getObjectState(virtual);
ValueNode[] entries = obj.getEntries();
ValueNode representation = virtual.getMaterializedRepresentation(fixed, entries, obj.getLocks());
escape(virtual.getObjectId(), representation);
obj = getObjectState(virtual);
PartialEscapeClosure.updateStatesForMaterialized(this, virtual, obj.getMaterializedValue());
if (representation instanceof AllocatedObjectNode) {
objects.add((AllocatedObjectNode) representation);
locks.add(LockState.asList(obj.getLocks()));
ensureVirtual.add(obj.getEnsureVirtualized());
int pos = values.size();
while (values.size() < pos + entries.length) {
values.add(null);
}
for (int i = 0; i < entries.length; i++) {
if (entries[i] instanceof VirtualObjectNode) {
VirtualObjectNode entryVirtual = (VirtualObjectNode) entries[i];
ObjectState entryObj = getObjectState(entryVirtual);
if (entryObj.isVirtual()) {
materializeWithCommit(fixed, entryVirtual, objects, locks, values, ensureVirtual, otherAllocations);
entryObj = getObjectState(entryVirtual);
}
values.set(pos + i, entryObj.getMaterializedValue());
} else {
values.set(pos + i, entries[i]);
}
}
objectMaterialized(virtual, (AllocatedObjectNode) representation, values.subList(pos, pos + entries.length));
} else {
VirtualUtil.trace(options, debug, "materialized %s as %s", virtual, representation);
otherAllocations.add(representation);
assert obj.getLocks() == null;
}
}
Aggregations