# HG changeset patch # User Lukas Stadler # Date 1347552747 -7200 # Node ID 466e6ceebfed9cd6dd42e320850e70e60c3fe51b # Parent adf0879a41c1977f2797de0ddd31e04cff64301e iterative partial escape analysis diff -r adf0879a41c1 -r 466e6ceebfed graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java Thu Sep 13 11:41:43 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java Thu Sep 13 18:12:27 2012 +0200 @@ -57,7 +57,9 @@ objectStates = new IdentityHashMap<>(); } if (!objectStates.containsKey(state.object())) { - objectStates.put(state.object(), state); + if (!(state instanceof MaterializedObjectState) || ((MaterializedObjectState) state).materializedValue() != state.object()) { + objectStates.put(state.object(), state); + } } } current = current.outerFrameState(); @@ -80,13 +82,13 @@ BoxedVirtualObjectNode boxedVirtualObjectNode = (BoxedVirtualObjectNode) vobj; entry.getValue().setValues(new Value[]{toValue(boxedVirtualObjectNode.getUnboxedValue())}); } else { - Value[] values = new Value[vobj.fieldsCount()]; + Value[] values = new Value[vobj.fields().length]; entry.getValue().setValues(values); if (values.length > 0) { changed = true; VirtualObjectState currentField = (VirtualObjectState) objectStates.get(vobj); assert currentField != null; - for (int i = 0; i < vobj.fieldsCount(); i++) { + for (int i = 0; i < vobj.fields().length; i++) { values[i] = toValue(currentField.fieldValues().get(i)); } } @@ -145,14 +147,14 @@ if (value instanceof VirtualObjectNode) { VirtualObjectNode obj = (VirtualObjectNode) value; EscapeObjectState state = objectStates.get(obj); - if (state == null && obj.fieldsCount() > 0) { + if (state == null && obj.fields().length > 0) { // null states occur for objects with 0 fields throw new GraalInternalError("no mapping found for virtual object %s", obj); } if (state instanceof MaterializedObjectState) { return toValue(((MaterializedObjectState) state).materializedValue()); } else { - assert obj.fieldsCount() == 0 || state instanceof VirtualObjectState; + assert obj.fields().length == 0 || state instanceof VirtualObjectState; VirtualObject ciObj = virtualObjects.get(value); if (ciObj == null) { ciObj = VirtualObject.get(obj.type(), null, virtualObjects.size()); diff -r adf0879a41c1 -r 466e6ceebfed graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/EscapeAnalysisPhase.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/EscapeAnalysisPhase.java Thu Sep 13 11:41:43 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/EscapeAnalysisPhase.java Thu Sep 13 18:12:27 2012 +0200 @@ -153,7 +153,7 @@ fields.put(escapeFields[i].representation(), i); } assert node.objectStamp().isExactType(); - final VirtualObjectNode virtual = graph.add(new VirtualObjectNode(id, node.objectStamp().type(), escapeFields.length)); + final VirtualObjectNode virtual = graph.add(new VirtualObjectNode(id, node.objectStamp().type(), escapeFields)); Debug.log("new virtual object: " + virtual); node.replaceAtUsages(virtual); FixedNode next = node.next(); @@ -167,7 +167,7 @@ } } - if (virtual.fieldsCount() > 0) { + if (virtual.fields().length > 0) { final BlockExitState startState = new BlockExitState(escapeFields, virtual); new PostOrderNodeIterator(next, startState) { diff -r adf0879a41c1 -r 466e6ceebfed graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/ea/PartialEscapeAnalysisPhase.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/ea/PartialEscapeAnalysisPhase.java Thu Sep 13 11:41:43 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/ea/PartialEscapeAnalysisPhase.java Thu Sep 13 18:12:27 2012 +0200 @@ -42,17 +42,31 @@ import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.virtual.*; -class EscapeRecord { +abstract class EscapeRecord { + + public final int id; + public final ResolvedJavaType type; + public final VirtualObjectNode virtualObject; - public final ResolvedJavaType type; + public EscapeRecord(int id, ResolvedJavaType type, VirtualObjectNode virtualObject) { + this.id = id; + this.type = type; + this.virtualObject = virtualObject; + } + + public abstract String fieldName(int index); + + public abstract int fieldCount(); +} + +class InstanceEscapeRecord extends EscapeRecord { + public final EscapeField[] fields; public final HashMap fieldMap = new HashMap<>(); - public final VirtualObjectNode virtualObject; - public EscapeRecord(ResolvedJavaType type, EscapeField[] fields, VirtualObjectNode virtualObject) { - this.type = type; + public InstanceEscapeRecord(int id, ResolvedJavaType type, VirtualObjectNode virtualObject, EscapeField[] fields) { + super(id, type, virtualObject); this.fields = fields; - this.virtualObject = virtualObject; for (int i = 0; i < fields.length; i++) { fieldMap.put(fields[i].representation(), i); } @@ -60,7 +74,42 @@ @Override public String toString() { - return MetaUtil.toJavaName(type, false) + "@" + (System.identityHashCode(this) % 10000); + return MetaUtil.toJavaName(type, false) + "@" + id; + } + + @Override + public String fieldName(int index) { + return fields[index].name(); + } + + @Override + public int fieldCount() { + return fields.length; + } +} + +class ArrayEscapeRecord extends EscapeRecord { + + public final int length; + + public ArrayEscapeRecord(int id, ResolvedJavaType type, VirtualObjectNode virtualObject, int length) { + super(id, type, virtualObject); + this.length = length; + } + + @Override + public String toString() { + return MetaUtil.toJavaName(type.componentType(), false) + "[" + length + "]@" + id; + } + + @Override + public String fieldName(int index) { + return "[" + index + "]"; + } + + @Override + public int fieldCount() { + return length; } } @@ -75,6 +124,9 @@ private static final DebugMetric metricOtherRemoved = Debug.metric("OtherRemoved"); private static final DebugMetric metricMaterializations = Debug.metric("Materializations"); private static final DebugMetric metricMaterializationFields = Debug.metric("MaterializationFields"); + private static final DebugMetric metricLoopBailouts = Debug.metric("LoopBailouts"); + private static final DebugMetric metricMonitorBailouts = Debug.metric("MonitorBailouts"); + private static final ValueNode DUMMY_NODE = new ValueNode(null) { }; @@ -94,7 +146,7 @@ private final SchedulePhase schedule; private final NodeBitMap usages; private final NodeBitMap visitedNodes; - private boolean changed = false; + boolean changed = false; private final boolean changeGraph; @@ -185,7 +237,7 @@ } if (fieldState != null) { for (int i = 0; i < fieldState.length; i++) { - str.append(record.fields[i].name()).append('=').append(fieldState[i]).append(' '); + str.append(record.fieldName(i)).append('=').append(fieldState[i]).append(' '); } } if (materializedValue != null) { @@ -232,7 +284,7 @@ if (changeGraph) { HashSet deferred = new HashSet<>(); ArrayList deferredStores = new ArrayList<>(); - materializeBefore(fixed, record, deferred, deferredStores); + materializeChangedBefore(fixed, record, deferred, deferredStores); for (FixedWithNextNode write : deferredStores) { write.setProbability(fixed.probability()); graph.addBeforeFixed(fixed, write); @@ -249,6 +301,7 @@ if (changeGraph) { error("object materialized with lock: %s\n", record); } + metricMonitorBailouts.increment(); throw new BailoutException("object materialized with lock"); } @@ -266,15 +319,16 @@ obj.initialized = true; } - private void materializeBefore(FixedNode fixed, EscapeRecord record, HashSet deferred, ArrayList deferredStores) { + private void materializeChangedBefore(FixedNode fixed, EscapeRecord record, HashSet deferred, ArrayList deferredStores) { trace("materializing %s at %s", record, fixed); ObjectState obj = objectState(record); if (obj.lockCount > 0) { error("object materialized with lock: %s\n", record); + metricMonitorBailouts.increment(); throw new BailoutException("object materialized with lock"); } - MaterializeObjectNode materialize = graph.add(new MaterializeObjectNode(record.type, record.fields)); + MaterializeObjectNode materialize = graph.add(new MaterializeObjectNode(record.type, record.virtualObject)); materialize.setProbability(fixed.probability()); ValueNode[] fieldState = obj.fieldState; metricMaterializations.increment(); @@ -286,15 +340,19 @@ ObjectState valueObj = objectState(fieldState[i]); if (valueObj != null) { if (valueObj.materializedValue == null) { - materializeBefore(fixed, valueObj.record, deferred, deferredStores); + materializeChangedBefore(fixed, valueObj.record, deferred, deferredStores); } if (deferred.contains(valueObj.record)) { + Kind fieldKind; if (record.type.isArrayClass()) { - deferredStores.add(graph.add(new StoreIndexedNode(materialize, ConstantNode.forInt(i, graph), record.type.componentType().kind(), valueObj.materializedValue, -1))); + deferredStores.add(graph.add(new CyclicMaterializeStoreNode(materialize, valueObj.materializedValue, i))); + fieldKind = record.type.componentType().kind(); } else { - deferredStores.add(graph.add(new StoreFieldNode(materialize, (ResolvedJavaField) record.fields[i].representation(), valueObj.materializedValue, -1))); + InstanceEscapeRecord instanceRecord = (InstanceEscapeRecord) record; + deferredStores.add(graph.add(new CyclicMaterializeStoreNode(materialize, valueObj.materializedValue, (ResolvedJavaField) instanceRecord.fields[i].representation()))); + fieldKind = instanceRecord.fields[i].type().kind(); } - materialize.values().set(i, ConstantNode.defaultForKind(record.fields[i].type().kind(), graph)); + materialize.values().set(i, ConstantNode.defaultForKind(fieldKind, graph)); } else { assert valueObj.initialized : "should be initialized: " + record + " at " + fixed; materialize.values().set(i, valueObj.materializedValue); @@ -373,12 +431,11 @@ } if (op != null) { - changed = true; trace("{{%s}} ", node); ResolvedJavaType type = op.type(); EscapeField[] fields = op.fields(); - VirtualObjectNode virtualObject = changeGraph ? graph.add(new VirtualObjectNode(virtualIds, type, fields.length)) : null; - EscapeRecord record = new EscapeRecord(type, fields, virtualObject); + VirtualObjectNode virtualObject = changeGraph ? graph.add(new VirtualObjectNode(virtualIds, type, fields)) : null; + EscapeRecord record = type.isArrayClass() ? new ArrayEscapeRecord(virtualIds, type, virtualObject, fields.length) : new InstanceEscapeRecord(virtualIds, type, virtualObject, fields); ValueNode[] fieldState = changeGraph ? op.fieldState() : new ValueNode[fields.length]; if (changeGraph) { metricAllocationRemoved.increment(); @@ -478,6 +535,7 @@ obj.lockCount--; } if (changeGraph) { + changed = true; if (obj.materializedValue == null) { metricLockRemoved.increment(); node.replaceFirstInput(x.object(), obj.record.virtualObject); @@ -488,16 +546,32 @@ } usageFound = true; } + } else if (node instanceof CyclicMaterializeStoreNode) { + CyclicMaterializeStoreNode x = (CyclicMaterializeStoreNode) node; + ObjectState obj = state.objectState(x.object()); + assert obj != null : x; + if (obj.record.type.isArrayClass()) { + obj.fieldState[x.targetIndex()] = x.value(); + } else { + InstanceEscapeRecord record = (InstanceEscapeRecord) obj.record; + int index = record.fieldMap.get(x.targetField()); + obj.fieldState[index] = x.value(); + } + if (changeGraph) { + graph.removeFixed(x); + } + usageFound = true; } else if (node instanceof LoadFieldNode) { LoadFieldNode x = (LoadFieldNode) node; ObjectState obj = state.objectState(x.object()); assert obj != null : x; - if (!obj.record.fieldMap.containsKey(x.field())) { + InstanceEscapeRecord record = (InstanceEscapeRecord) obj.record; + if (!record.fieldMap.containsKey(x.field())) { // the field does not exist in the virtual object ensureMaterialized(state, obj, x); } if (obj.materializedValue == null) { - int index = obj.record.fieldMap.get(x.field()); + int index = record.fieldMap.get(x.field()); ValueNode result = obj.fieldState[index]; ObjectState resultObj = state.objectState(result); if (resultObj != null) { @@ -511,6 +585,7 @@ if (changeGraph) { metricLoadRemoved.increment(); } + changed = true; } else { if (changeGraph) { x.replaceFirstInput(x.object(), obj.materializedValue); @@ -523,17 +598,19 @@ ValueNode value = x.value(); ObjectState obj = state.objectState(object); if (obj != null) { - if (!obj.record.fieldMap.containsKey(x.field())) { + InstanceEscapeRecord record = (InstanceEscapeRecord) obj.record; + if (!record.fieldMap.containsKey(x.field())) { // the field does not exist in the virtual object ensureMaterialized(state, obj, x); } if (obj.materializedValue == null) { - int index = obj.record.fieldMap.get(x.field()); + int index = record.fieldMap.get(x.field()); obj.fieldState[index] = value; if (changeGraph) { graph.removeFixed(x); metricStoreRemoved.increment(); } + changed = true; } else { if (changeGraph) { x.replaceFirstInput(object, obj.materializedValue); @@ -575,6 +652,7 @@ if (changeGraph) { metricLoadRemoved.increment(); } + changed = true; } } else { if (changeGraph) { @@ -605,6 +683,7 @@ graph.removeFixed(x); metricStoreRemoved.increment(); } + changed = true; } } else { if (changeGraph) { @@ -631,7 +710,7 @@ ObjectState obj = state.objectState(x.array()); assert obj != null : x; if (changeGraph) { - graph.replaceFixedWithFloating(x, ConstantNode.forInt(obj.record.fields.length, graph)); + graph.replaceFixedWithFloating(x, ConstantNode.forInt(((ArrayEscapeRecord) obj.record).length, graph)); metricOtherRemoved.increment(); } usageFound = true; @@ -671,11 +750,13 @@ graph.replaceFloating(x, ConstantNode.forBoolean(false, graph)); usageFound = true; metricOtherRemoved.increment(); + changed = true; } else if (xVirtual && yVirtual) { // both are virtual: check if they refer to the same object graph.replaceFloating(x, ConstantNode.forBoolean(xObj == yObj, graph)); usageFound = true; metricOtherRemoved.increment(); + changed = true; } else { assert xObj != null || yObj != null; if (xObj != null) { @@ -726,13 +807,14 @@ break; } } - assert virtualObj != null; - virtual.add(virtualObj); + if (virtualObj != null) { + virtual.add(virtualObj); + } } } }); for (ObjectState obj : state.states()) { - if (obj.lockCount > 0) { + if (obj.materializedValue == null && obj.lockCount > 0) { virtual.add(obj); } } @@ -939,7 +1021,7 @@ if (i == 0) { sameRecord = obj.record; sameType = obj.record.type; - sameFieldCount = obj.record.fields.length; + sameFieldCount = obj.record.fieldCount(); } else { if (sameRecord != obj.record) { sameRecord = null; @@ -947,7 +1029,7 @@ if (sameType != obj.record.type) { sameType = null; } - if (sameFieldCount != obj.record.fields.length) { + if (sameFieldCount != obj.record.fieldCount()) { sameFieldCount = -1; } } @@ -1045,6 +1127,7 @@ if (changeGraph) { error("object materialized within loop: %s\n", obj.record); } + metricLoopBailouts.increment(); throw new BailoutException("object materialized within loop"); } for (int i = 0; endObj.fieldState != null && i < endObj.fieldState.length; i++) { @@ -1104,30 +1187,38 @@ @Override protected void run(StructuredGraph graph) { + iteration(graph, 0); + } + + + private void iteration(final StructuredGraph graph, final int num) { HashSet allocations = new HashSet<>(); SchedulePhase schedule = new SchedulePhase(); schedule.apply(graph, false); + EscapeAnalysisIteration iteration = null; try { - new EscapeAnalysisIteration(graph, schedule, runtime, allocations, false).run(); + iteration = new EscapeAnalysisIteration(graph, schedule, runtime, allocations, false); + iteration.run(); } catch (BailoutException e) { // do nothing if the if the escape analysis bails out during the analysis iteration... return; } - try { - new EscapeAnalysisIteration(graph, schedule, runtime, allocations, true).run(); - new CanonicalizerPhase(target, runtime, assumptions).apply(graph); - } catch (BailoutException e) { - throw new GraalInternalError(e); - } - } - - public static boolean isValidConstantIndex(AccessIndexedNode x) { - Constant index = x.index().asConstant(); - if (x.array() instanceof NewArrayNode) { - Constant length = ((NewArrayNode) x.array()).dimension(0).asConstant(); - return index != null && length != null && index.asInt() >= 0 && index.asInt() < length.asInt(); - } else { - return false; + if (iteration.changed) { + try { + new EscapeAnalysisIteration(graph, schedule, runtime, allocations, true).run(); + new CanonicalizerPhase(target, runtime, assumptions).apply(graph); + } catch (BailoutException e) { + throw new GraalInternalError(e); + } + // next round... + if (num < 2) { + Debug.scope("next", new Runnable() { + @Override + public void run() { + iteration(graph, num + 1); + } + }); + } } } } diff -r adf0879a41c1 -r 466e6ceebfed graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CyclicMaterializeStoreNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CyclicMaterializeStoreNode.java Thu Sep 13 18:12:27 2012 +0200 @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2009, 2011, 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.java; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; + +/** + * The {@code StoreFieldNode} represents a write to a static or instance field. + */ +@NodeInfo(nameTemplate = "MaterializeStore#{p#field/s}") +public final class CyclicMaterializeStoreNode extends FixedWithNextNode implements Lowerable { + + @Input private ValueNode object; + @Input private ValueNode value; + private final Object target; + + public ValueNode object() { + return object; + } + + public ValueNode value() { + return value; + } + + public ResolvedJavaField targetField() { + return (ResolvedJavaField) target; + } + + public int targetIndex() { + return (int) target; + } + + public CyclicMaterializeStoreNode(ValueNode object, ValueNode value, ResolvedJavaField field) { + super(StampFactory.forVoid()); + this.object = object; + this.value = value; + this.target = field; + } + + public CyclicMaterializeStoreNode(ValueNode object, ValueNode value, int index) { + super(StampFactory.forVoid()); + this.object = object; + this.value = value; + this.target = index; + } + + @Override + public void lower(LoweringTool tool) { + StructuredGraph graph = (StructuredGraph) graph(); + ResolvedJavaType type = object.objectStamp().type(); + FixedWithNextNode store; + if (target instanceof Integer) { + store = graph.add(new StoreIndexedNode(object, ConstantNode.forInt((int) target, graph), type.componentType().kind(), value, -1)); + } else { + assert target instanceof ResolvedJavaField; + store = graph.add(new StoreFieldNode(object, (ResolvedJavaField) target, value, -1)); + } + graph.replaceFixedWithFixed(this, store); + } +} diff -r adf0879a41c1 -r 466e6ceebfed graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MaterializeObjectNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MaterializeObjectNode.java Thu Sep 13 11:41:43 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MaterializeObjectNode.java Thu Sep 13 18:12:27 2012 +0200 @@ -35,24 +35,20 @@ public final class MaterializeObjectNode extends FixedWithNextNode implements EscapeAnalyzable, Lowerable, Node.IterableNodeType, Canonicalizable { @Input private final NodeInputList values; + @Input private final VirtualObjectNode virtualObject; private final ResolvedJavaType type; - private final EscapeField[] fields; - public MaterializeObjectNode(ResolvedJavaType type, EscapeField[] fields) { + public MaterializeObjectNode(ResolvedJavaType type, VirtualObjectNode virtualObject) { super(StampFactory.exactNonNull(type)); this.type = type; - this.fields = fields; - this.values = new NodeInputList<>(this, fields.length); + this.virtualObject = virtualObject; + this.values = new NodeInputList<>(this, virtualObject.fields().length); } public ResolvedJavaType type() { return type; } - public EscapeField[] getFields() { - return fields; - } - public NodeInputList values() { return values; } @@ -60,6 +56,7 @@ @Override public void lower(LoweringTool tool) { StructuredGraph graph = (StructuredGraph) graph(); + EscapeField[] fields = virtualObject.fields(); if (type.isArrayClass()) { ResolvedJavaType element = type.componentType(); NewArrayNode newArray; @@ -118,7 +115,7 @@ @Override public EscapeField[] fields() { - return fields; + return virtualObject.fields(); } @Override diff -r adf0879a41c1 -r 466e6ceebfed graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/BoxedVirtualObjectNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/BoxedVirtualObjectNode.java Thu Sep 13 11:41:43 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/BoxedVirtualObjectNode.java Thu Sep 13 18:12:27 2012 +0200 @@ -33,7 +33,7 @@ @Input ValueNode unboxedValue; public BoxedVirtualObjectNode(int id, ResolvedJavaType type, ValueNode unboxedValue) { - super(id, type, 1); + super(id, type, new EscapeField[1]); this.unboxedValue = unboxedValue; } diff -r adf0879a41c1 -r 466e6ceebfed graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java Thu Sep 13 11:41:43 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java Thu Sep 13 18:12:27 2012 +0200 @@ -27,22 +27,23 @@ import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; + @NodeInfo(nameTemplate = "VirtualObject {p#type}") public class VirtualObjectNode extends FloatingNode implements LIRLowerable { @SuppressWarnings("unused") private final int id; private final ResolvedJavaType type; - private final int fieldsCount; + private final EscapeField[] fields; - public VirtualObjectNode(int id, ResolvedJavaType type, int fieldCount) { + public VirtualObjectNode(int id, ResolvedJavaType type, EscapeField[] fields) { super(StampFactory.virtual()); this.id = id; this.type = type; - this.fieldsCount = fieldCount; + this.fields = fields; } - public JavaType type() { + public ResolvedJavaType type() { return type; } @@ -60,7 +61,7 @@ } } - public int fieldsCount() { - return fieldsCount; + public EscapeField[] fields() { + return fields; } } diff -r adf0879a41c1 -r 466e6ceebfed graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectState.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectState.java Thu Sep 13 11:41:43 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectState.java Thu Sep 13 18:12:27 2012 +0200 @@ -41,13 +41,13 @@ public VirtualObjectState(VirtualObjectNode object, ValueNode[] fieldValues) { super(object); - assert object.fieldsCount() == fieldValues.length; + assert object.fields().length == fieldValues.length; this.fieldValues = new NodeInputList<>(this, fieldValues); } private VirtualObjectState(VirtualObjectNode object, List fieldValues) { super(object); - assert object.fieldsCount() == fieldValues.size(); + assert object.fields().length == fieldValues.size(); this.fieldValues = new NodeInputList<>(this, fieldValues); }