# HG changeset patch # User Lukas Stadler # Date 1437480881 -7200 # Node ID e8dc090e167f50bb7ff8806e7edf24bfc46d76be # Parent e4efc2b03eb4cbdb3c4bbd9ba750a165edcf416a keep "ensureVirtual" flag for objects during escape analysis diff -r e4efc2b03eb4 -r e8dc090e167f graal/com.oracle.graal.api.directives/src/com/oracle/graal/api/directives/GraalDirectives.java --- a/graal/com.oracle.graal.api.directives/src/com/oracle/graal/api/directives/GraalDirectives.java Tue Jul 21 14:09:39 2015 +0200 +++ b/graal/com.oracle.graal.api.directives/src/com/oracle/graal/api/directives/GraalDirectives.java Tue Jul 21 14:14:41 2015 +0200 @@ -283,4 +283,17 @@ } return value; } + + /** + * Ensures that the given object will be virtual (escape analyzed) at all points that are + * dominated by the current position. + */ + public static void ensureVirtualized(@SuppressWarnings("unused") Object object) { + } + + /** + * Ensures that the given object will be virtual at the current position. + */ + public static void ensureVirtualizedHere(@SuppressWarnings("unused") Object object) { + } } diff -r e4efc2b03eb4 -r e8dc090e167f graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAAssertionsTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAAssertionsTest.java Tue Jul 21 14:14:41 2015 +0200 @@ -0,0 +1,235 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.test.ea; + +import jdk.internal.jvmci.code.*; + +import org.junit.*; + +import com.oracle.graal.api.directives.*; +import com.oracle.graal.compiler.test.*; + +public class PEAAssertionsTest extends GraalCompilerTest { + + public static Object field; + + public static void snippet1(int i) { + Integer object = new Integer(i); + GraalDirectives.ensureVirtualized(object); + } + + @Test + public void test1() { + test("snippet1", 1); + } + + public static void snippet2(int i) { + Integer object = new Integer(i); + GraalDirectives.ensureVirtualized(object); + field = object; // assert here + } + + @Test(expected = SourceStackTrace.class) + public void test2() { + test("snippet2", 1); + } + + public static void snippet3(int i) { + Integer object = new Integer(i); + field = object; + GraalDirectives.ensureVirtualized(object); // assert here + } + + @Test(expected = SourceStackTrace.class) + public void test3() { + test("snippet3", 1); + } + + public static void snippetHere1(int i) { + Integer object = new Integer(i); + GraalDirectives.ensureVirtualizedHere(object); + } + + @Test + public void testHere1() { + test("snippetHere1", 1); + } + + public static void snippetHere2(int i) { + Integer object = new Integer(i); + GraalDirectives.ensureVirtualizedHere(object); + field = object; + } + + @Test + public void testHere2() { + test("snippetHere2", 1); + } + + public static void snippetHere3(int i) { + Integer object = new Integer(i); + field = object; + GraalDirectives.ensureVirtualizedHere(object); // assert here + } + + @Test(expected = SourceStackTrace.class) + public void testHere3() { + test("snippetHere3", 1); + } + + public static void snippetBoxing1(int i) { + Integer object = i; + GraalDirectives.ensureVirtualizedHere(object); // assert here + } + + @Test(expected = SourceStackTrace.class) + public void testBoxing1() { + test("snippetBoxing1", 1); + } + + public static void snippetBoxing2(int i) { + Integer object = i; + GraalDirectives.ensureVirtualized(object); // assert here + field = object; + } + + @Test(expected = SourceStackTrace.class) + public void testBoxing2() { + test("snippetBoxing2", 1); + } + + public static void snippetControlFlow1(boolean b, int i) { + Integer object = new Integer(i); + if (b) { + GraalDirectives.ensureVirtualized(object); + } + field = object; + } + + @Test + public void testControlFlow1() { + test("snippetControlFlow1", true, 1); + } + + public static void snippetControlFlow2(boolean b, int i) { + Integer object = new Integer(i); + if (b) { + GraalDirectives.ensureVirtualized(object); + } else { + GraalDirectives.ensureVirtualized(object); + } + field = object; // assert here + } + + @Test(expected = SourceStackTrace.class) + public void testControlFlow2() { + test("snippetControlFlow2", true, 1); + } + + public static void snippetControlFlow3(boolean b, int i) { + Integer object = new Integer(i); + GraalDirectives.ensureVirtualized(object); + if (b) { + field = 1; + } else { + field = 2; + } + field = object; // assert here + } + + @Test(expected = SourceStackTrace.class) + public void testControlFlow3() { + test("snippetControlFlow3", true, 1); + } + + public static void snippetControlFlow4(boolean b, int i) { + Integer object = new Integer(i); + if (b) { + field = object; + } else { + field = 2; + } + GraalDirectives.ensureVirtualized(object); // assert here + } + + @Test(expected = SourceStackTrace.class) + public void testControlFlow4() { + test("snippetControlFlow4", true, 1); + } + + public static void snippetControlFlow5(boolean b, int i) { + Integer object = new Integer(i); + if (b) { + field = object; + } else { + field = 2; + } + GraalDirectives.ensureVirtualizedHere(object); // assert here + } + + @Test(expected = SourceStackTrace.class) + public void testControlFlow5() { + test("snippetControlFlow5", true, 1); + } + + public static final class TestClass { + Object a; + Object b; + } + + public static void snippetIndirect1(boolean b, int i) { + Integer object = new Integer(i); + TestClass t = new TestClass(); + t.a = object; + GraalDirectives.ensureVirtualized(object); + + if (b) { + field = t; // assert here + } else { + field = 2; + } + } + + @Test(expected = SourceStackTrace.class) + public void testIndirect1() { + test("snippetIndirect1", true, 1); + } + + public static void snippetIndirect2(boolean b, int i) { + Integer object = new Integer(i); + TestClass t = new TestClass(); + t.a = object; + GraalDirectives.ensureVirtualized(t); + + if (b) { + field = object; + } else { + field = 2; + } + } + + @Test + public void testIndirect2() { + test("snippetIndirect2", true, 1); + } +} diff -r e4efc2b03eb4 -r e8dc090e167f graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java Tue Jul 21 14:09:39 2015 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java Tue Jul 21 14:14:41 2015 +0200 @@ -82,7 +82,7 @@ VirtualBoxingNode newVirtual = new VirtualBoxingNode(type, boxingKind); assert newVirtual.getFields().length == 1; - tool.createVirtualObject(newVirtual, new ValueNode[]{v}, Collections. emptyList()); + tool.createVirtualObject(newVirtual, new ValueNode[]{v}, Collections. emptyList(), false); tool.replaceWithVirtual(newVirtual); } } diff -r e4efc2b03eb4 -r e8dc090e167f graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java Tue Jul 21 14:09:39 2015 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java Tue Jul 21 14:14:41 2015 +0200 @@ -84,7 +84,7 @@ state[i] = defaultForKind; } VirtualObjectNode virtualObject = createVirtualArrayNode(constantLength); - tool.createVirtualObject(virtualObject, state, Collections. emptyList()); + tool.createVirtualObject(virtualObject, state, Collections. emptyList(), false); tool.replaceWithVirtual(virtualObject); } } diff -r e4efc2b03eb4 -r e8dc090e167f graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java Tue Jul 21 14:09:39 2015 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java Tue Jul 21 14:14:41 2015 +0200 @@ -79,7 +79,7 @@ for (int i = 0; i < state.length; i++) { state[i] = defaultFieldValue(fields[i]); } - tool.createVirtualObject(virtualObject, state, Collections. emptyList()); + tool.createVirtualObject(virtualObject, state, Collections. emptyList(), false); tool.replaceWithVirtual(virtualObject); } } diff -r e4efc2b03eb4 -r e8dc090e167f graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Virtualizable.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Virtualizable.java Tue Jul 21 14:09:39 2015 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Virtualizable.java Tue Jul 21 14:14:41 2015 +0200 @@ -52,6 +52,10 @@ public abstract MonitorIdNode removeLock(); public abstract ValueNode getMaterializedValue(); + + public abstract void setEnsureVirtualized(boolean ensureVirtualized); + + public abstract boolean getEnsureVirtualized(); } /** diff -r e4efc2b03eb4 -r e8dc090e167f graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/VirtualizerTool.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/VirtualizerTool.java Tue Jul 21 14:09:39 2015 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/VirtualizerTool.java Tue Jul 21 14:14:41 2015 +0200 @@ -67,8 +67,9 @@ * @param virtualObject the new virtual object. * @param entryState the initial state of the virtual object's fields. * @param locks the initial locking depths. + * @param ensureVirtualized true if this object needs to stay virtual */ - void createVirtualObject(VirtualObjectNode virtualObject, ValueNode[] entryState, List locks); + void createVirtualObject(VirtualObjectNode virtualObject, ValueNode[] entryState, List locks, boolean ensureVirtualized); /** * Queries the current state of the given value: if it is virtualized (thread-local and the diff -r e4efc2b03eb4 -r e8dc090e167f graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/CommitAllocationNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/CommitAllocationNode.java Tue Jul 21 14:09:39 2015 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/CommitAllocationNode.java Tue Jul 21 14:14:41 2015 +0200 @@ -36,10 +36,12 @@ public final class CommitAllocationNode extends FixedWithNextNode implements VirtualizableAllocation, Lowerable, Simplifiable { public static final NodeClass TYPE = NodeClass.create(CommitAllocationNode.class); + @Input NodeInputList virtualObjects = new NodeInputList<>(this); @Input NodeInputList values = new NodeInputList<>(this); @Input(InputType.Association) NodeInputList locks = new NodeInputList<>(this); protected ArrayList lockIndexes = new ArrayList<>(Arrays.asList(0)); + protected ArrayList ensureVirtual = new ArrayList<>(); public CommitAllocationNode() { super(TYPE, StampFactory.forVoid()); @@ -57,6 +59,10 @@ return locks.subList(lockIndexes.get(objIndex), lockIndexes.get(objIndex + 1)); } + public List getEnsureVirtual() { + return ensureVirtual; + } + @Override public boolean verify() { assertTrue(virtualObjects.size() + 1 == lockIndexes.size(), "lockIndexes size doesn't match " + virtualObjects + ", " + lockIndexes); @@ -66,11 +72,17 @@ valueCount += virtual.entryCount(); } assertTrue(values.size() == valueCount, "values size doesn't match"); + assertTrue(virtualObjects.size() == ensureVirtual.size(), "ensureVirtual size doesn't match"); return super.verify(); } @Override public void lower(LoweringTool tool) { + for (int i = 0; i < virtualObjects.size(); i++) { + if (ensureVirtual.get(i)) { + EnsureVirtualizedNode.ensureVirtualFailure(this, virtualObjects.get(i).stamp()); + } + } tool.getLowerer().lower(this, tool); } @@ -90,7 +102,7 @@ for (int i = 0; i < virtualObjects.size(); i++) { VirtualObjectNode virtualObject = virtualObjects.get(i); int entryCount = virtualObject.entryCount(); - tool.createVirtualObject(virtualObject, values.subList(pos, pos + entryCount).toArray(new ValueNode[entryCount]), getLocks(i)); + tool.createVirtualObject(virtualObject, values.subList(pos, pos + entryCount).toArray(new ValueNode[entryCount]), getLocks(i), ensureVirtual.get(i)); pos += entryCount; } tool.delete(); @@ -166,6 +178,7 @@ List newVirtualObjects = new ArrayList<>(usedCount); List newLocks = new ArrayList<>(usedCount); ArrayList newLockIndexes = new ArrayList<>(usedCount + 1); + ArrayList newEnsureVirtual = new ArrayList<>(usedCount); newLockIndexes.add(0); List newValues = new ArrayList<>(); int valuePos = 0; @@ -176,6 +189,7 @@ newLocks.addAll(getLocks(objIndex)); newLockIndexes.add(newLocks.size()); newValues.addAll(values.subList(valuePos, valuePos + virtualObject.entryCount())); + newEnsureVirtual.add(ensureVirtual.get(objIndex)); } valuePos += virtualObject.entryCount(); } @@ -186,6 +200,7 @@ values.clear(); values.addAll(newValues); lockIndexes = newLockIndexes; + ensureVirtual = newEnsureVirtual; } } diff -r e4efc2b03eb4 -r e8dc090e167f graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/EnsureVirtualizedNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/EnsureVirtualizedNode.java Tue Jul 21 14:14:41 2015 +0200 @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.nodes.virtual; + +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.util.*; + +@NodeInfo +public final class EnsureVirtualizedNode extends FixedWithNextNode implements Virtualizable, Lowerable { + + public static final NodeClass TYPE = NodeClass.create(EnsureVirtualizedNode.class); + + @Input ValueNode object; + private final boolean localOnly; + + public EnsureVirtualizedNode(ValueNode object, boolean localOnly) { + super(TYPE, StampFactory.forVoid()); + this.object = object; + this.localOnly = localOnly; + } + + public void virtualize(VirtualizerTool tool) { + State state = tool.getObjectState(object); + if (state != null && state.getState() == EscapeState.Virtual) { + if (state.getVirtualObject() instanceof VirtualBoxingNode) { + Throwable exception = new VerificationError("ensureVirtual is not valid for boxing objects: %s", state.getVirtualObject().type().getName()); + throw GraphUtil.approxSourceException(this, exception); + } + if (!localOnly) { + state.setEnsureVirtualized(true); + } + tool.delete(); + } + } + + public void lower(LoweringTool tool) { + ensureVirtualFailure(this, object.stamp()); + } + + public static void ensureVirtualFailure(Node location, Stamp stamp) { + Throwable exception = new VerificationError("Object should not be materialized (stamp=%s):", stamp); + throw GraphUtil.approxSourceException(location, exception); + } +} diff -r e4efc2b03eb4 -r e8dc090e167f graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/StandardGraphBuilderPlugins.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/StandardGraphBuilderPlugins.java Tue Jul 21 14:09:39 2015 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/StandardGraphBuilderPlugins.java Tue Jul 21 14:14:41 2015 +0200 @@ -46,6 +46,7 @@ import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.util.*; +import com.oracle.graal.nodes.virtual.*; import com.oracle.graal.replacements.nodes.*; import com.oracle.graal.replacements.nodes.arithmetic.*; @@ -663,6 +664,19 @@ return true; } }); + + r.register1("ensureVirtualized", Object.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode object) { + b.add(new EnsureVirtualizedNode(object, false)); + return true; + } + }); + r.register1("ensureVirtualizedHere", Object.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode object) { + b.add(new EnsureVirtualizedNode(object, true)); + return true; + } + }); } private static void registerJMHBlackholePlugins(InvocationPlugins plugins) { diff -r e4efc2b03eb4 -r e8dc090e167f graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BasicObjectCloneNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BasicObjectCloneNode.java Tue Jul 21 14:09:39 2015 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BasicObjectCloneNode.java Tue Jul 21 14:14:41 2015 +0200 @@ -66,7 +66,7 @@ /* * Looks at the given stamp and determines if it is an exact type (or can be assumed to be an * exact type) and if it is a cloneable type. - * + * * If yes, then the exact type is returned, otherwise it returns null. */ protected static ResolvedJavaType getConcreteType(Stamp stamp, Assumptions assumptions, MetaAccessProvider metaAccess) { @@ -99,7 +99,7 @@ newEntryState[i] = originalState.getEntry(i); } VirtualObjectNode newVirtual = originalVirtual.duplicate(); - tool.createVirtualObject(newVirtual, newEntryState, Collections. emptyList()); + tool.createVirtualObject(newVirtual, newEntryState, Collections. emptyList(), false); tool.replaceWithVirtual(newVirtual); } } else { @@ -120,7 +120,7 @@ state[i] = loads[i] = new LoadFieldNode(obj, fields[i]); tool.addNode(loads[i]); } - tool.createVirtualObject(newVirtual, state, Collections. emptyList()); + tool.createVirtualObject(newVirtual, state, Collections. emptyList(), false); tool.replaceWithVirtual(newVirtual); } } diff -r e4efc2b03eb4 -r e8dc090e167f graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/MaterializeFrameNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/MaterializeFrameNode.java Tue Jul 21 14:09:39 2015 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/MaterializeFrameNode.java Tue Jul 21 14:14:41 2015 +0200 @@ -25,7 +25,6 @@ import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; -import com.oracle.truffle.api.frame.*; /** * Intrinsic node for materializing a Truffle frame. @@ -44,7 +43,4 @@ public ValueNode getFrame() { return frame; } - - @NodeIntrinsic - public static native MaterializedFrame materialize(VirtualFrame frame); } diff -r e4efc2b03eb4 -r e8dc090e167f graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/NewFrameNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/NewFrameNode.java Tue Jul 21 14:09:39 2015 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/NewFrameNode.java Tue Jul 21 14:14:41 2015 +0200 @@ -182,12 +182,12 @@ graph().getAssumptions().record(new AssumptionValidAssumption((OptimizedAssumption) frameDescriptor.getVersion())); } - tool.createVirtualObject(virtualFrameObjectArray, objectArrayEntryState, Collections. emptyList()); + tool.createVirtualObject(virtualFrameObjectArray, objectArrayEntryState, Collections. emptyList(), false); if (virtualFramePrimitiveArray != null) { - tool.createVirtualObject(virtualFramePrimitiveArray, primitiveArrayEntryState, Collections. emptyList()); + tool.createVirtualObject(virtualFramePrimitiveArray, primitiveArrayEntryState, Collections. emptyList(), false); } if (virtualFrameTagArray != null) { - tool.createVirtualObject(virtualFrameTagArray, tagArrayEntryState, Collections. emptyList()); + tool.createVirtualObject(virtualFrameTagArray, tagArrayEntryState, Collections. emptyList(), false); } assert frameFields.length == 5 || frameFields.length == 3; @@ -202,7 +202,7 @@ if (tagsField != null) { frameEntryState[frameFieldList.indexOf(tagsField)] = virtualFrameTagArray; } - tool.createVirtualObject(virtualFrame, frameEntryState, Collections. emptyList()); + tool.createVirtualObject(virtualFrame, frameEntryState, Collections. emptyList(), false); tool.replaceWithVirtual(virtualFrame); } diff -r e4efc2b03eb4 -r e8dc090e167f graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ObjectState.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ObjectState.java Tue Jul 21 14:09:39 2015 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ObjectState.java Tue Jul 21 14:14:41 2015 +0200 @@ -49,28 +49,31 @@ private ValueNode[] entries; private ValueNode materializedValue; private LockState locks; + private boolean ensureVirtualized; private EscapeObjectState cachedState; - public ObjectState(VirtualObjectNode virtual, ValueNode[] entries, EscapeState state, List locks) { - this(virtual, entries, state, (LockState) null); + public ObjectState(VirtualObjectNode virtual, ValueNode[] entries, EscapeState state, List locks, boolean ensureVirtualized) { + this(virtual, entries, state, (LockState) null, ensureVirtualized); for (int i = locks.size() - 1; i >= 0; i--) { this.locks = new LockState(locks.get(i), this.locks); } } - public ObjectState(VirtualObjectNode virtual, ValueNode[] entries, EscapeState state, LockState locks) { + public ObjectState(VirtualObjectNode virtual, ValueNode[] entries, EscapeState state, LockState locks, boolean ensureVirtualized) { this.virtual = virtual; this.entries = entries; this.state = state; this.locks = locks; + this.ensureVirtualized = ensureVirtualized; } - public ObjectState(VirtualObjectNode virtual, ValueNode materializedValue, EscapeState state, LockState locks) { + public ObjectState(VirtualObjectNode virtual, ValueNode materializedValue, EscapeState state, LockState locks, boolean ensureVirtualized) { this.virtual = virtual; this.materializedValue = materializedValue; this.state = state; this.locks = locks; + this.ensureVirtualized = ensureVirtualized; } private ObjectState(ObjectState other) { @@ -80,6 +83,7 @@ locks = other.locks; state = other.state; cachedState = other.cachedState; + ensureVirtualized = other.ensureVirtualized; } public ObjectState cloneState() { @@ -185,6 +189,16 @@ } @Override + public void setEnsureVirtualized(boolean ensureVirtualized) { + this.ensureVirtualized = ensureVirtualized; + } + + @Override + public boolean getEnsureVirtualized() { + return ensureVirtualized; + } + + @Override public String toString() { StringBuilder str = new StringBuilder().append('{'); if (locks != null) { diff -r e4efc2b03eb4 -r e8dc090e167f graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeBlockState.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeBlockState.java Tue Jul 21 14:09:39 2015 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeBlockState.java Tue Jul 21 14:14:41 2015 +0200 @@ -74,7 +74,8 @@ List values = new ArrayList<>(8); List> locks = new ArrayList<>(2); List otherAllocations = new ArrayList<>(2); - materializeWithCommit(fixed, virtual, objects, locks, values, otherAllocations, state); + List ensureVirtual = new ArrayList<>(2); + materializeWithCommit(fixed, virtual, objects, locks, values, ensureVirtual, otherAllocations, state); materializeEffects.add("materializeBefore", (graph, obsoleteNodes) -> { for (ValueNode otherAllocation : otherAllocations) { @@ -102,6 +103,7 @@ for (List monitorIds : locks) { commit.addLocks(monitorIds); } + commit.getEnsureVirtual().addAll(ensureVirtual); assert commit.usages().filter(AllocatedObjectNode.class).count() == commit.getUsageCount(); List materializedValues = commit.usages().filter(AllocatedObjectNode.class).snapshot(); @@ -115,7 +117,7 @@ } private void materializeWithCommit(FixedNode fixed, VirtualObjectNode virtual, List objects, List> locks, List values, - List otherAllocations, EscapeState state) { + List ensureVirtual, List otherAllocations, EscapeState state) { ObjectState obj = getObjectState(virtual); ValueNode[] entries = obj.getEntries(); @@ -125,6 +127,7 @@ 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); @@ -133,7 +136,7 @@ if (entries[i] instanceof VirtualObjectNode) { ObjectState entryObj = getObjectState((VirtualObjectNode) entries[i]); if (entryObj.isVirtual()) { - materializeWithCommit(fixed, entryObj.getVirtualObject(), objects, locks, values, otherAllocations, state); + materializeWithCommit(fixed, entryObj.getVirtualObject(), objects, locks, values, ensureVirtual, otherAllocations, state); } values.set(pos + i, entryObj.getMaterializedValue()); } else { diff -r e4efc2b03eb4 -r e8dc090e167f graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Tue Jul 21 14:09:39 2015 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Tue Jul 21 14:14:41 2015 +0200 @@ -562,7 +562,7 @@ materialized |= mergeObjectStates(object, objStates, states); } else { if (uniqueMaterializedValue != null) { - newState.addObject(object, new ObjectState(object, uniqueMaterializedValue, EscapeState.Materialized, null)); + newState.addObject(object, new ObjectState(object, uniqueMaterializedValue, EscapeState.Materialized, null, false)); } else { PhiNode materializedValuePhi = getPhi(object, StampFactory.forKind(Kind.Object)); mergeEffects.addFloatingNode(materializedValuePhi, "materializedPhi"); @@ -574,7 +574,7 @@ } setPhiInput(materializedValuePhi, i, obj.getMaterializedValue()); } - newState.addObject(object, new ObjectState(object, materializedValuePhi, EscapeState.Materialized, null)); + newState.addObject(object, new ObjectState(object, materializedValuePhi, EscapeState.Materialized, null, false)); } } } @@ -615,6 +615,7 @@ */ private boolean mergeObjectStates(VirtualObjectNode object, ObjectState[] objStates, List blockStates) { boolean compatible = true; + boolean ensureVirtual = true; ValueNode[] values = objStates[0].getEntries().clone(); // determine all entries that have a two-slot value @@ -622,6 +623,7 @@ outer: for (int i = 0; i < objStates.length; i++) { ValueNode[] entries = objStates[i].getEntries(); int valueIndex = 0; + ensureVirtual &= objStates[i].getEnsureVirtualized(); while (valueIndex < values.length) { Kind otherKind = entries[valueIndex].getKind(); Kind entryKind = object.entryKind(valueIndex); @@ -705,7 +707,7 @@ values[i] = phi; } } - newState.addObject(object, new ObjectState(object, values, EscapeState.Virtual, objStates[0].getLocks())); + newState.addObject(object, new ObjectState(object, values, EscapeState.Virtual, objStates[0].getLocks(), ensureVirtual)); return materialized; } else { // not compatible: materialize in all predecessors @@ -716,7 +718,7 @@ ensureMaterialized(blockStates.get(i), obj, predecessor.getEndNode(), blockEffects.get(predecessor), METRIC_MATERIALIZATIONS_MERGE); setPhiInput(materializedValuePhi, i, obj.getMaterializedValue()); } - newState.addObject(object, new ObjectState(object, materializedValuePhi, EscapeState.Materialized, null)); + newState.addObject(object, new ObjectState(object, materializedValuePhi, EscapeState.Materialized, null, false)); return true; } } diff -r e4efc2b03eb4 -r e8dc090e167f graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualizerToolImpl.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualizerToolImpl.java Tue Jul 21 14:09:39 2015 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualizerToolImpl.java Tue Jul 21 14:14:41 2015 +0200 @@ -151,7 +151,7 @@ } @Override - public void createVirtualObject(VirtualObjectNode virtualObject, ValueNode[] entryState, List locks) { + public void createVirtualObject(VirtualObjectNode virtualObject, ValueNode[] entryState, List locks, boolean ensureVirtualized) { VirtualUtil.trace("{{%s}} ", current); if (!virtualObject.isAlive()) { effects.addFloatingNode(virtualObject, "newVirtualObject"); @@ -166,7 +166,7 @@ } } } - state.addObject(virtualObject, new ObjectState(virtualObject, entryState, EscapeState.Virtual, locks)); + state.addObject(virtualObject, new ObjectState(virtualObject, entryState, EscapeState.Virtual, locks, ensureVirtualized)); closure.addAndMarkAlias(virtualObject, virtualObject); PartialEscapeClosure.METRIC_ALLOCATION_REMOVED.increment(); }