< prev index next >
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PartialEscapeClosure.java
Print this page
@@ -57,10 +57,11 @@
import org.graalvm.compiler.nodes.NodeView;
import org.graalvm.compiler.nodes.PhiNode;
import org.graalvm.compiler.nodes.ProxyNode;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult;
+import org.graalvm.compiler.nodes.UnwindNode;
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.ValuePhiNode;
import org.graalvm.compiler.nodes.ValueProxyNode;
import org.graalvm.compiler.nodes.VirtualState;
import org.graalvm.compiler.nodes.VirtualState.NodeClosure;
@@ -103,11 +104,10 @@
/**
* The indexes into this array correspond to {@link VirtualObjectNode#getObjectId()}.
*/
public final ArrayList<VirtualObjectNode> virtualObjects = new ArrayList<>();
- public final DebugContext debug;
@Override
public boolean needsApplyEffects() {
if (hasChanged()) {
return true;
@@ -187,11 +187,10 @@
public PartialEscapeClosure(ScheduleResult schedule, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, ConstantFieldProvider constantFieldProvider,
LoweringProvider loweringProvider) {
super(schedule, schedule.getCFG());
StructuredGraph graph = schedule.getCFG().graph;
this.hasVirtualInputs = graph.createNodeBitMap();
- this.debug = graph.getDebug();
this.tool = new VirtualizerToolImpl(metaAccess, constantReflection, constantFieldProvider, this, graph.getAssumptions(), graph.getOptions(), debug, loweringProvider);
}
/**
* @return true if the node was deleted, false otherwise
@@ -685,20 +684,48 @@
}
// calculate the set of virtual objects that exist in all predecessors
int[] virtualObjTemp = intersectVirtualObjects(states);
+ boolean forceMaterialization = false;
+ ValueNode forcedMaterializationValue = null;
+ FrameState frameState = merge.stateAfter();
+ if (frameState != null && frameState.isExceptionHandlingBCI()) {
+ // We can not go below merges with an exception handling bci
+ // it could create allocations whose slow-path has an invalid framestate
+ forceMaterialization = true;
+ // check if we can reduce the scope of forced materialization to one phi node
+ if (frameState.stackSize() == 1 && merge.next() instanceof UnwindNode) {
+ assert frameState.outerFrameState() == null;
+ UnwindNode unwind = (UnwindNode) merge.next();
+ if (unwind.exception() == frameState.stackAt(0)) {
+ boolean nullLocals = true;
+ for (int i = 0; i < frameState.localsSize(); i++) {
+ if (frameState.localAt(i) != null) {
+ nullLocals = false;
+ break;
+ }
+ }
+ if (nullLocals) {
+ // We found that the merge is directly followed by an unwind
+ // the Framestate only has the thrown value on the stack and no locals
+ forcedMaterializationValue = unwind.exception();
+ }
+ }
+ }
+ }
+
boolean materialized;
do {
materialized = false;
- if (PartialEscapeBlockState.identicalObjectStates(states)) {
+ if (!forceMaterialization && PartialEscapeBlockState.identicalObjectStates(states)) {
newState.adoptAddObjectStates(states[0]);
} else {
for (int object : virtualObjTemp) {
- if (PartialEscapeBlockState.identicalObjectStates(states, object)) {
+ if (!forceMaterialization && PartialEscapeBlockState.identicalObjectStates(states, object)) {
newState.addObject(object, states[0].getObjectState(object).share());
continue;
}
// determine if all inputs are virtual or the same materialized value
@@ -708,10 +735,26 @@
boolean ensureVirtual = true;
ValueNode uniqueMaterializedValue = startObj.isVirtual() ? null : startObj.getMaterializedValue();
for (int i = 0; i < states.length; i++) {
ObjectState obj = states[i].getObjectState(object);
ensureVirtual &= obj.getEnsureVirtualized();
+ if (forceMaterialization) {
+ if (forcedMaterializationValue == null) {
+ uniqueMaterializedValue = null;
+ continue;
+ } else {
+ ValueNode value = forcedMaterializationValue;
+ if (merge.isPhiAtMerge(value)) {
+ value = ((ValuePhiNode) value).valueAt(i);
+ }
+ ValueNode alias = getAlias(value);
+ if (alias instanceof VirtualObjectNode && ((VirtualObjectNode) alias).getObjectId() == object) {
+ uniqueMaterializedValue = null;
+ continue;
+ }
+ }
+ }
if (obj.isVirtual()) {
virtualCount++;
uniqueMaterializedValue = null;
locksMatch &= obj.locksEqual(startObj);
} else if (obj.getMaterializedValue() != uniqueMaterializedValue) {
@@ -1027,10 +1070,11 @@
* check whether we trivially see that this is the only reference to
* this allocation
*/
if (virtual.hasIdentity() && !isSingleUsageAllocation(getPhiValueAt(phi, i), virtualObjs, states[i])) {
compatible = false;
+ break;
}
}
}
if (compatible) {
VirtualObjectNode virtual = getValueObjectVirtual(phi, virtualObjs[0]);
< prev index next >