# HG changeset patch # User Lukas Stadler # Date 1347629217 -7200 # Node ID 6ad5bf2efb5ede66f822387cc3877e820014020b # Parent bced4f3a41744760075752535e7093020389dfc4 cleanups, merge EscapeRecord and VirtualObjectNode diff -r bced4f3a4174 -r 6ad5bf2efb5e 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 Fri Sep 14 15:16:50 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java Fri Sep 14 15:26:57 2012 +0200 @@ -82,13 +82,13 @@ BoxedVirtualObjectNode boxedVirtualObjectNode = (BoxedVirtualObjectNode) vobj; entry.getValue().setValues(new Value[]{toValue(boxedVirtualObjectNode.getUnboxedValue())}); } else { - Value[] values = new Value[vobj.fields().length]; + Value[] values = new Value[vobj.entryCount()]; 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.fields().length; i++) { + for (int i = 0; i < vobj.entryCount(); i++) { values[i] = toValue(currentField.fieldValues().get(i)); } } @@ -147,14 +147,14 @@ if (value instanceof VirtualObjectNode) { VirtualObjectNode obj = (VirtualObjectNode) value; EscapeObjectState state = objectStates.get(obj); - if (state == null && obj.fields().length > 0) { + if (state == null && obj.entryCount() > 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.fields().length == 0 || state instanceof VirtualObjectState; + assert obj.entryCount() == 0 || state instanceof VirtualObjectState; VirtualObject ciObj = virtualObjects.get(value); if (ciObj == null) { ciObj = VirtualObject.get(obj.type(), null, virtualObjects.size()); diff -r bced4f3a4174 -r 6ad5bf2efb5e 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 Fri Sep 14 15:16:50 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/ea/PartialEscapeAnalysisPhase.java Fri Sep 14 15:26:57 2012 +0200 @@ -42,77 +42,6 @@ import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.virtual.*; -abstract class EscapeRecord { - - public final int id; - public final ResolvedJavaType type; - public final VirtualObjectNode virtualObject; - - 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 InstanceEscapeRecord(int id, ResolvedJavaType type, VirtualObjectNode virtualObject, EscapeField[] fields) { - super(id, type, virtualObject); - this.fields = fields; - for (int i = 0; i < fields.length; i++) { - fieldMap.put(fields[i].representation(), i); - } - } - - @Override - public String toString() { - 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; - } -} - class EscapeAnalysisIteration { // Metrics @@ -145,11 +74,11 @@ private final MetaAccessProvider runtime; private final SchedulePhase schedule; private final NodeBitMap usages; - private final NodeBitMap visitedNodes; boolean changed = false; private final boolean changeGraph; + private final HashSet reusedVirtualObjects = new HashSet<>(); private final HashSet allocations; private final ArrayList obsoleteNodes = new ArrayList<>(); private int virtualIds = 0; @@ -160,7 +89,6 @@ this.runtime = runtime; this.allocations = allocations; this.changeGraph = changeGraph; - this.visitedNodes = graph.createNodeBitMap(); this.usages = graph.createNodeBitMap(); } @@ -183,41 +111,33 @@ if (changed) { Debug.log("escape analysis on %s\n", graph.method()); } - - if (GraalOptions.TraceEscapeAnalysis) { - for (Node node : graph.getNodes()) { - if (!visitedNodes.isMarked(node) && !(node instanceof VirtualState) && !(node instanceof VirtualObjectNode)) { - trace("unvisited node: %s", node); - } - } - } } } private static class ObjectState { - public final EscapeRecord record; + public final VirtualObjectNode virtual; public ValueNode[] fieldState; public ValueNode materializedValue; public int lockCount; public boolean initialized; - public ObjectState(EscapeRecord record, ValueNode[] fieldState, int lockCount) { - this.record = record; + public ObjectState(VirtualObjectNode virtual, ValueNode[] fieldState, int lockCount) { + this.virtual = virtual; this.fieldState = fieldState; this.lockCount = lockCount; this.initialized = false; } - public ObjectState(EscapeRecord record, ValueNode materializedValue, int lockCount) { - this.record = record; + public ObjectState(VirtualObjectNode virtual, ValueNode materializedValue, int lockCount) { + this.virtual = virtual; this.materializedValue = materializedValue; this.lockCount = lockCount; this.initialized = true; } private ObjectState(ObjectState other) { - record = other.record; + virtual = other.virtual; fieldState = other.fieldState == null ? null : other.fieldState.clone(); materializedValue = other.materializedValue; lockCount = other.lockCount; @@ -237,7 +157,7 @@ } if (fieldState != null) { for (int i = 0; i < fieldState.length; i++) { - str.append(record.fieldName(i)).append('=').append(fieldState[i]).append(' '); + str.append(virtual.fieldName(i)).append('=').append(fieldState[i]).append(' '); } } if (materializedValue != null) { @@ -250,29 +170,29 @@ private class BlockState implements MergeableBlockState { - private final HashMap recordStates = new HashMap<>(); - private final HashMap recordAliases = new HashMap<>(); + private final HashMap objectStates = new HashMap<>(); + private final HashMap objectAliases = new HashMap<>(); public BlockState() { } public BlockState(BlockState other) { - for (Map.Entry entry : other.recordStates.entrySet()) { - recordStates.put(entry.getKey(), entry.getValue().clone()); + for (Map.Entry entry : other.objectStates.entrySet()) { + objectStates.put(entry.getKey(), entry.getValue().clone()); } - for (Map.Entry entry : other.recordAliases.entrySet()) { - recordAliases.put(entry.getKey(), entry.getValue()); + for (Map.Entry entry : other.objectAliases.entrySet()) { + objectAliases.put(entry.getKey(), entry.getValue()); } } - public ObjectState objectState(EscapeRecord record) { - assert recordStates.containsKey(record); - return recordStates.get(record); + public ObjectState objectState(VirtualObjectNode object) { + assert objectStates.containsKey(object); + return objectStates.get(object); } public ObjectState objectState(ValueNode value) { - EscapeRecord record = recordAliases.get(value); - return record == null ? null : objectState(record); + VirtualObjectNode object = objectAliases.get(value); + return object == null ? null : objectState(object); } @Override @@ -280,26 +200,26 @@ return new BlockState(this); } - public void materializeBefore(FixedNode fixed, EscapeRecord record) { + public void materializeBefore(FixedNode fixed, VirtualObjectNode virtual) { if (changeGraph) { - HashSet deferred = new HashSet<>(); + HashSet deferred = new HashSet<>(); ArrayList deferredStores = new ArrayList<>(); - materializeChangedBefore(fixed, record, deferred, deferredStores); + materializeChangedBefore(fixed, virtual, deferred, deferredStores); for (FixedWithNextNode write : deferredStores) { write.setProbability(fixed.probability()); graph.addBeforeFixed(fixed, write); } } else { - materializeUnchangedBefore(record); + materializeUnchangedBefore(virtual); } } - private void materializeUnchangedBefore(EscapeRecord record) { - trace("materializing %s", record); - ObjectState obj = objectState(record); + private void materializeUnchangedBefore(VirtualObjectNode virtual) { + trace("materializing %s", virtual); + ObjectState obj = objectState(virtual); if (obj.lockCount > 0) { if (changeGraph) { - error("object materialized with lock: %s\n", record); + error("object materialized with lock: %s\n", virtual); } metricMonitorBailouts.increment(); throw new BailoutException("object materialized with lock"); @@ -312,75 +232,75 @@ ObjectState valueObj = objectState(fieldState[i]); if (valueObj != null) { if (valueObj.materializedValue == null) { - materializeUnchangedBefore(valueObj.record); + materializeUnchangedBefore(valueObj.virtual); } } } obj.initialized = true; } - private void materializeChangedBefore(FixedNode fixed, EscapeRecord record, HashSet deferred, ArrayList deferredStores) { - trace("materializing %s at %s", record, fixed); - ObjectState obj = objectState(record); + private void materializeChangedBefore(FixedNode fixed, VirtualObjectNode virtual, HashSet deferred, ArrayList deferredStores) { + trace("materializing %s at %s", virtual, fixed); + ObjectState obj = objectState(virtual); if (obj.lockCount > 0) { - error("object materialized with lock: %s\n", record); + error("object materialized with lock: %s\n", virtual); metricMonitorBailouts.increment(); throw new BailoutException("object materialized with lock"); } - MaterializeObjectNode materialize = graph.add(new MaterializeObjectNode(record.type, record.virtualObject)); + MaterializeObjectNode materialize = graph.add(new MaterializeObjectNode(virtual)); materialize.setProbability(fixed.probability()); ValueNode[] fieldState = obj.fieldState; metricMaterializations.increment(); metricMaterializationFields.add(fieldState.length); obj.fieldState = null; obj.materializedValue = materialize; - deferred.add(record); + deferred.add(virtual); for (int i = 0; i < fieldState.length; i++) { ObjectState valueObj = objectState(fieldState[i]); if (valueObj != null) { if (valueObj.materializedValue == null) { - materializeChangedBefore(fixed, valueObj.record, deferred, deferredStores); + materializeChangedBefore(fixed, valueObj.virtual, deferred, deferredStores); } - if (deferred.contains(valueObj.record)) { + if (deferred.contains(valueObj.virtual)) { Kind fieldKind; - if (record.type.isArrayClass()) { + if (virtual instanceof VirtualArrayNode) { deferredStores.add(graph.add(new CyclicMaterializeStoreNode(materialize, valueObj.materializedValue, i))); - fieldKind = record.type.componentType().kind(); + fieldKind = ((VirtualArrayNode) virtual).componentType().kind(); } else { - InstanceEscapeRecord instanceRecord = (InstanceEscapeRecord) record; - deferredStores.add(graph.add(new CyclicMaterializeStoreNode(materialize, valueObj.materializedValue, (ResolvedJavaField) instanceRecord.fields[i].representation()))); - fieldKind = instanceRecord.fields[i].type().kind(); + VirtualInstanceNode instanceObject = (VirtualInstanceNode) virtual; + deferredStores.add(graph.add(new CyclicMaterializeStoreNode(materialize, valueObj.materializedValue, instanceObject.field(i)))); + fieldKind = instanceObject.field(i).type().kind(); } materialize.values().set(i, ConstantNode.defaultForKind(fieldKind, graph)); } else { - assert valueObj.initialized : "should be initialized: " + record + " at " + fixed; + assert valueObj.initialized : "should be initialized: " + virtual + " at " + fixed; materialize.values().set(i, valueObj.materializedValue); } } else { materialize.values().set(i, fieldState[i]); } } - deferred.remove(record); + deferred.remove(virtual); obj.initialized = true; graph.addBeforeFixed(fixed, materialize); } - private void addAndMarkAlias(EscapeRecord record, ValueNode node) { - addAlias(record, node); + private void addAndMarkAlias(VirtualObjectNode virtual, ValueNode node, boolean remove) { + objectAliases.put(node, virtual); for (Node usage : node.usages()) { - assert !visitedNodes.isMarked(usage) : "used by already visited node: " + node + " -> " + usage; - usages.mark(usage); - if (usage instanceof VirtualState) { - markVirtualUsages(usage); - } + markVirtualUsages(usage); } - obsoleteNodes.add(node); + if (remove) { + obsoleteNodes.add(node); + } } private void markVirtualUsages(Node node) { - usages.mark(node); + if (!usages.isNew(node)) { + usages.mark(node); + } if (node instanceof VirtualState) { for (Node usage : node.usages()) { markVirtualUsages(usage); @@ -388,21 +308,17 @@ } } - public void addAlias(EscapeRecord record, ValueNode alias) { - recordAliases.put(alias, record); - } - - public void addRecord(EscapeRecord record, ObjectState state) { - recordStates.put(record, state); + public void addObject(VirtualObjectNode virtual, ObjectState state) { + objectStates.put(virtual, state); } public Iterable states() { - return recordStates.values(); + return objectStates.values(); } @Override public String toString() { - return recordStates.toString(); + return objectStates.toString(); } } @@ -432,23 +348,26 @@ if (op != null) { trace("{{%s}} ", node); - ResolvedJavaType type = op.type(); - EscapeField[] fields = op.fields(); - 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]; + VirtualObjectNode virtualObject = op.virtualObject(virtualIds); + if (virtualObject.isAlive()) { + reusedVirtualObjects.add(virtualObject); + state.addAndMarkAlias(virtualObject, virtualObject, false); + } else { + if (changeGraph) { + virtualObject = graph.add(virtualObject); + } + } + ValueNode[] fieldState = changeGraph ? op.fieldState() : new ValueNode[virtualObject.entryCount()]; if (changeGraph) { metricAllocationRemoved.increment(); metricAllocationFieldsRemoved.add(fieldState.length); } else { allocations.add((ValueNode) node); } - state.addRecord(record, new ObjectState(record, fieldState, 0)); - state.addAndMarkAlias(record, (ValueNode) node); + state.addObject(virtualObject, new ObjectState(virtualObject, fieldState, 0)); + state.addAndMarkAlias(virtualObject, (ValueNode) node, true); virtualIds++; } else { - visitedNodes.mark(node); - if (changeGraph && node instanceof LoopExitNode) { for (ObjectState obj : state.states()) { if (obj.fieldState != null) { @@ -487,7 +406,7 @@ ObjectState obj = state.objectState(value); assert obj != null : node; if (obj.materializedValue == null) { - state.addAndMarkAlias(obj.record, node); + state.addAndMarkAlias(obj.virtual, node, true); } else { if (changeGraph) { node.replaceFirstInput(value, obj.materializedValue); @@ -499,9 +418,9 @@ ObjectState obj = state.objectState(x.object()); assert obj != null : x; if (obj.materializedValue == null) { - if (x.targetClass() != null && obj.record.type.isSubtypeOf(x.targetClass())) { + if (x.targetClass() != null && obj.virtual.type().isSubtypeOf(x.targetClass())) { metricOtherRemoved.increment(); - state.addAndMarkAlias(obj.record, x); + state.addAndMarkAlias(obj.virtual, x, true); // throw new UnsupportedOperationException("probably incorrect - losing dependency"); } else { replaceWithMaterialized(x.object(), x, state, obj); @@ -527,7 +446,7 @@ AccessMonitorNode x = (AccessMonitorNode) node; ObjectState obj = state.objectState(x.object()); if (obj != null) { - Debug.log("monitor operation %s on %s\n", x, obj.record); + Debug.log("monitor operation %s on %s\n", x, obj.virtual); if (node instanceof MonitorEnterNode) { obj.lockCount++; } else { @@ -538,7 +457,7 @@ changed = true; if (obj.materializedValue == null) { metricLockRemoved.increment(); - node.replaceFirstInput(x.object(), obj.record.virtualObject); + node.replaceFirstInput(x.object(), obj.virtual); x.eliminate(); } else { node.replaceFirstInput(x.object(), obj.materializedValue); @@ -550,11 +469,11 @@ CyclicMaterializeStoreNode x = (CyclicMaterializeStoreNode) node; ObjectState obj = state.objectState(x.object()); assert obj != null : x; - if (obj.record.type.isArrayClass()) { + if (obj.virtual instanceof VirtualArrayNode) { obj.fieldState[x.targetIndex()] = x.value(); } else { - InstanceEscapeRecord record = (InstanceEscapeRecord) obj.record; - int index = record.fieldMap.get(x.targetField()); + VirtualInstanceNode instance = (VirtualInstanceNode) obj.virtual; + int index = instance.fieldIndex(x.targetField()); obj.fieldState[index] = x.value(); } if (changeGraph) { @@ -565,17 +484,17 @@ LoadFieldNode x = (LoadFieldNode) node; ObjectState obj = state.objectState(x.object()); assert obj != null : x; - InstanceEscapeRecord record = (InstanceEscapeRecord) obj.record; - if (!record.fieldMap.containsKey(x.field())) { + VirtualInstanceNode virtual = (VirtualInstanceNode) obj.virtual; + int fieldIndex = virtual.fieldIndex(x.field()); + if (fieldIndex == -1) { // the field does not exist in the virtual object ensureMaterialized(state, obj, x); } if (obj.materializedValue == null) { - int index = record.fieldMap.get(x.field()); - ValueNode result = obj.fieldState[index]; + ValueNode result = obj.fieldState[fieldIndex]; ObjectState resultObj = state.objectState(result); if (resultObj != null) { - state.addAndMarkAlias(resultObj.record, x); + state.addAndMarkAlias(resultObj.virtual, x, true); } else { if (changeGraph) { x.replaceAtUsages(result); @@ -598,14 +517,14 @@ ValueNode value = x.value(); ObjectState obj = state.objectState(object); if (obj != null) { - InstanceEscapeRecord record = (InstanceEscapeRecord) obj.record; - if (!record.fieldMap.containsKey(x.field())) { + VirtualInstanceNode virtual = (VirtualInstanceNode) obj.virtual; + int fieldIndex = virtual.fieldIndex(x.field()); + if (fieldIndex == -1) { // the field does not exist in the virtual object ensureMaterialized(state, obj, x); } if (obj.materializedValue == null) { - int index = record.fieldMap.get(x.field()); - obj.fieldState[index] = value; + obj.fieldState[fieldIndex] = value; if (changeGraph) { graph.removeFixed(x); metricStoreRemoved.increment(); @@ -642,7 +561,7 @@ ValueNode result = arrayObj.fieldState[index]; ObjectState resultObj = state.objectState(result); if (resultObj != null) { - state.addAndMarkAlias(resultObj.record, x); + state.addAndMarkAlias(resultObj.virtual, x, true); } else { if (changeGraph) { x.replaceAtUsages(result); @@ -710,7 +629,7 @@ ObjectState obj = state.objectState(x.array()); assert obj != null : x; if (changeGraph) { - graph.replaceFixedWithFloating(x, ConstantNode.forInt(((ArrayEscapeRecord) obj.record).length, graph)); + graph.replaceFixedWithFloating(x, ConstantNode.forInt(((VirtualArrayNode) obj.virtual).entryCount(), graph)); metricOtherRemoved.increment(); } changed = true; @@ -720,7 +639,7 @@ ObjectState obj = state.objectState(x.object()); assert obj != null : x; if (changeGraph) { - ConstantNode hub = ConstantNode.forConstant(obj.record.type.getEncoding(Representation.ObjectHub), runtime, graph); + ConstantNode hub = ConstantNode.forConstant(obj.virtual.type().getEncoding(Representation.ObjectHub), runtime, graph); graph.replaceFixedWithFloating(x, hub); metricOtherRemoved.increment(); } @@ -800,11 +719,11 @@ ObjectState valueObj = state.objectState(value); if (valueObj != null) { virtual.add(valueObj); - usage.replaceFirstInput(value, valueObj.record.virtualObject); + usage.replaceFirstInput(value, valueObj.virtual); } else if (value instanceof VirtualObjectNode) { ObjectState virtualObj = null; for (ObjectState obj : state.states()) { - if (value == obj.record.virtualObject) { + if (value == obj.virtual) { virtualObj = obj; break; } @@ -844,19 +763,23 @@ ObjectState valueObj = state.objectState(fieldState[i]); if (valueObj != null) { if (valueObj.materializedValue == null) { - fieldState[i] = valueObj.record.virtualObject; + fieldState[i] = valueObj.virtual; } else { fieldState[i] = valueObj.materializedValue; } } } - v = graph.add(new VirtualObjectState(obj.record.virtualObject, fieldState)); + v = graph.add(new VirtualObjectState(obj.virtual, fieldState)); } else { - v = graph.add(new MaterializedObjectState(obj.record.virtualObject, obj.materializedValue)); + v = graph.add(new MaterializedObjectState(obj.virtual, obj.materializedValue)); } - for (EscapeObjectState s : stateAfter.virtualObjectMappings()) { - if (s.object() == v.object()) { - throw new GraalInternalError("unexpected duplicate virtual state at: %s for %s", node, v.object()); + for (int i = 0; i < stateAfter.virtualObjectMappingCount(); i++) { + if (stateAfter.virtualObjectMappingAt(i).object() == v.object()) { + if (reusedVirtualObjects.contains(v.object())) { + stateAfter.virtualObjectMappings().remove(i); + } else { + throw new GraalInternalError("unexpected duplicate virtual state at: %s for %s", node, v.object()); + } } } stateAfter.addVirtualObjectMapping(v); @@ -880,7 +803,7 @@ private void ensureMaterialized(BlockState state, ObjectState obj, FixedNode materializeBefore) { assert obj != null; if (obj.materializedValue == null) { - state.materializeBefore(materializeBefore, obj.record); + state.materializeBefore(materializeBefore, obj.virtual); } assert obj.materializedValue != null; } @@ -903,14 +826,14 @@ protected BlockState merge(MergeNode merge, List states) { BlockState newState = new BlockState(); - newState.recordAliases.putAll(states.get(0).recordAliases); + newState.objectAliases.putAll(states.get(0).objectAliases); for (int i = 1; i < states.size(); i++) { BlockState state = states.get(i); - for (Map.Entry entry : states.get(0).recordAliases.entrySet()) { - if (state.recordAliases.containsKey(entry.getKey())) { - assert state.recordAliases.get(entry.getKey()) == entry.getValue(); + for (Map.Entry entry : states.get(0).objectAliases.entrySet()) { + if (state.objectAliases.containsKey(entry.getKey())) { + assert state.objectAliases.get(entry.getKey()) == entry.getValue(); } else { - newState.recordAliases.remove(entry.getKey()); + newState.objectAliases.remove(entry.getKey()); } } } @@ -923,13 +846,13 @@ do { materialized = false; // use a hash set to make the values distinct... - for (EscapeRecord record : new HashSet<>(newState.recordAliases.values())) { - ObjectState resultState = newState.recordStates.get(record); + for (VirtualObjectNode object : new HashSet<>(newState.objectAliases.values())) { + ObjectState resultState = newState.objectStates.get(object); if (resultState == null || resultState.materializedValue == null) { int virtual = 0; - int lockCount = states.get(0).objectState(record).lockCount; + int lockCount = states.get(0).objectState(object).lockCount; for (BlockState state : states) { - ObjectState obj = state.objectState(record); + ObjectState obj = state.objectState(object); if (obj.materializedValue == null) { virtual++; } @@ -940,23 +863,23 @@ ValueNode materializedValuePhi = changeGraph ? graph.add(new PhiNode(Kind.Object, merge)) : DUMMY_NODE; for (int i = 0; i < states.size(); i++) { BlockState state = states.get(i); - ObjectState obj = state.objectState(record); + ObjectState obj = state.objectState(object); materialized |= obj.materializedValue == null; ensureMaterialized(state, obj, merge.forwardEndAt(i)); if (changeGraph) { ((PhiNode) materializedValuePhi).addInput(obj.materializedValue); } } - newState.addRecord(record, new ObjectState(record, materializedValuePhi, lockCount)); + newState.addObject(object, new ObjectState(object, materializedValuePhi, lockCount)); } else { assert virtual == states.size(); - ValueNode[] values = states.get(0).objectState(record).fieldState.clone(); + ValueNode[] values = states.get(0).objectState(object).fieldState.clone(); PhiNode[] phis = new PhiNode[values.length]; boolean[] phiCreated = new boolean[values.length]; int mismatch = 0; for (int i = 1; i < states.size(); i++) { BlockState state = states.get(i); - ValueNode[] fields = state.objectState(record).fieldState; + ValueNode[] fields = state.objectState(object).fieldState; for (int index = 0; index < values.length; index++) { if (!phiCreated[index] && values[index] != fields[index]) { mismatch++; @@ -970,7 +893,7 @@ if (mismatch > 0) { for (int i = 0; i < states.size(); i++) { BlockState state = states.get(i); - ValueNode[] fields = state.objectState(record).fieldState; + ValueNode[] fields = state.objectState(object).fieldState; for (int index = 0; index < values.length; index++) { if (phiCreated[index]) { ObjectState obj = state.objectState(fields[index]); @@ -991,14 +914,13 @@ } } } - newState.addRecord(record, new ObjectState(record, values, lockCount)); + newState.addObject(object, new ObjectState(object, values, lockCount)); } } } for (PhiNode phi : merge.phis().snapshot()) { if (usages.isMarked(phi) && phi.type() == PhiType.Value) { - visitedNodes.mark(phi); materialized |= processPhi(newState, merge, phi, states); } } @@ -1011,9 +933,9 @@ assert states.size() == phi.valueCount(); int virtualInputs = 0; boolean materialized = false; - EscapeRecord sameRecord = null; + VirtualObjectNode sameObject = null; ResolvedJavaType sameType = null; - int sameFieldCount = -1; + int sameEntryCount = -1; for (int i = 0; i < phi.valueCount(); i++) { ValueNode value = phi.valueAt(i); ObjectState obj = states.get(i).objectState(value); @@ -1021,18 +943,18 @@ if (obj.materializedValue == null) { virtualInputs++; if (i == 0) { - sameRecord = obj.record; - sameType = obj.record.type; - sameFieldCount = obj.record.fieldCount(); + sameObject = obj.virtual; + sameType = obj.virtual.type(); + sameEntryCount = obj.virtual.entryCount(); } else { - if (sameRecord != obj.record) { - sameRecord = null; + if (sameObject != obj.virtual) { + sameObject = null; } - if (sameType != obj.record.type) { + if (sameType != obj.virtual.type()) { sameType = null; } - if (sameFieldCount != obj.record.fieldCount()) { - sameFieldCount = -1; + if (sameEntryCount != obj.virtual.entryCount()) { + sameEntryCount = -1; } } } else { @@ -1046,9 +968,9 @@ if (virtualInputs == 0) { // nothing to do... } else if (virtualInputs == phi.valueCount()) { - if (sameRecord != null) { - newState.addAndMarkAlias(sameRecord, phi); - } else if (sameType != null && sameFieldCount != -1) { + if (sameObject != null) { + newState.addAndMarkAlias(sameObject, phi, true); + } else if (sameType != null && sameEntryCount != -1) { materialize = true; // throw new GraalInternalError("merge required for %s", sameType); } else { @@ -1124,10 +1046,10 @@ Iterator iter = loopEnds.iterator(); for (BlockState loopEndState : loopEndStates) { LoopEndNode loopEnd = iter.next(); - ObjectState endObj = loopEndState.objectState(obj.record); + ObjectState endObj = loopEndState.objectState(obj.virtual); if (endObj.fieldState == null) { if (changeGraph) { - error("object materialized within loop: %s\n", obj.record); + error("object materialized within loop: %s\n", obj.virtual); } metricLoopBailouts.increment(); throw new BailoutException("object materialized within loop"); diff -r bced4f3a4174 -r 6ad5bf2efb5e graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeBitMap.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeBitMap.java Fri Sep 14 15:16:50 2012 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeBitMap.java Fri Sep 14 15:26:57 2012 +0200 @@ -111,7 +111,7 @@ private boolean check(Node node) { assert node.graph() == graph : "this node is not part of the graph"; - assert !isNew(node) : "node was added to the graph after creating the node bitmap"; + assert !isNew(node) : "node was added to the graph after creating the node bitmap: " + node; assert node.isAlive() : "node is deleted!"; return true; } diff -r bced4f3a4174 -r 6ad5bf2efb5e graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java Fri Sep 14 15:16:50 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java Fri Sep 14 15:26:57 2012 +0200 @@ -211,7 +211,7 @@ return virtualObjectMappings.size(); } - public Node virtualObjectMappingAt(int i) { + public EscapeObjectState virtualObjectMappingAt(int i) { return virtualObjectMappings.get(i); } diff -r bced4f3a4174 -r 6ad5bf2efb5e 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 Fri Sep 14 15:16:50 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MaterializeObjectNode.java Fri Sep 14 15:26:57 2012 +0200 @@ -22,8 +22,6 @@ */ package com.oracle.graal.nodes.java; -import java.util.*; - import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; @@ -31,22 +29,16 @@ import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.virtual.*; -@NodeInfo(nameTemplate = "Materialize {p#type/s}") +@NodeInfo(nameTemplate = "Materialize {i#virtualObject}") 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; - public MaterializeObjectNode(ResolvedJavaType type, VirtualObjectNode virtualObject) { - super(StampFactory.exactNonNull(type)); - this.type = type; + public MaterializeObjectNode(VirtualObjectNode virtualObject) { + super(StampFactory.exactNonNull(virtualObject.type())); this.virtualObject = virtualObject; - this.values = new NodeInputList<>(this, virtualObject.fields().length); - } - - public ResolvedJavaType type() { - return type; + this.values = new NodeInputList<>(this, virtualObject.entryCount()); } public NodeInputList values() { @@ -56,34 +48,38 @@ @Override public void lower(LoweringTool tool) { StructuredGraph graph = (StructuredGraph) graph(); - EscapeField[] fields = virtualObject.fields(); - if (type.isArrayClass()) { - ResolvedJavaType element = type.componentType(); - NewArrayNode newArray; - if (element.kind() == Kind.Object) { - newArray = graph.add(new NewObjectArrayNode(element, ConstantNode.forInt(fields.length, graph), false)); - } else { - newArray = graph.add(new NewPrimitiveArrayNode(element, ConstantNode.forInt(fields.length, graph), false)); - } - this.replaceAtUsages(newArray); - graph.addAfterFixed(this, newArray); + if (virtualObject instanceof VirtualInstanceNode) { + VirtualInstanceNode virtual = (VirtualInstanceNode) virtualObject; - FixedWithNextNode position = newArray; - for (int i = 0; i < fields.length; i++) { - StoreIndexedNode store = graph.add(new StoreIndexedNode(newArray, ConstantNode.forInt(i, graph), element.kind(), values.get(i), -1)); + NewInstanceNode newInstance = graph.add(new NewInstanceNode(virtual.type(), false)); + this.replaceAtUsages(newInstance); + graph.addAfterFixed(this, newInstance); + + FixedWithNextNode position = newInstance; + for (int i = 0; i < virtual.entryCount(); i++) { + StoreFieldNode store = graph.add(new StoreFieldNode(newInstance, virtual.field(i), values.get(i), -1)); graph.addAfterFixed(position, store); position = store; } graph.removeFixed(this); } else { - NewInstanceNode newInstance = graph.add(new NewInstanceNode(type, false)); - this.replaceAtUsages(newInstance); - graph.addAfterFixed(this, newInstance); + assert virtualObject instanceof VirtualArrayNode; + VirtualArrayNode virtual = (VirtualArrayNode) virtualObject; - FixedWithNextNode position = newInstance; - for (int i = 0; i < fields.length; i++) { - StoreFieldNode store = graph.add(new StoreFieldNode(newInstance, (ResolvedJavaField) fields[i].representation(), values.get(i), -1)); + ResolvedJavaType element = virtual.componentType(); + NewArrayNode newArray; + if (element.kind() == Kind.Object) { + newArray = graph.add(new NewObjectArrayNode(element, ConstantNode.forInt(virtual.entryCount(), graph), false)); + } else { + newArray = graph.add(new NewPrimitiveArrayNode(element, ConstantNode.forInt(virtual.entryCount(), graph), false)); + } + this.replaceAtUsages(newArray); + graph.addAfterFixed(this, newArray); + + FixedWithNextNode position = newArray; + for (int i = 0; i < virtual.entryCount(); i++) { + StoreIndexedNode store = graph.add(new StoreIndexedNode(newArray, ConstantNode.forInt(i, graph), element.kind(), values.get(i), -1)); graph.addAfterFixed(position, store); position = store; } @@ -103,34 +99,17 @@ @Override public EscapeOp getEscapeOp() { - return new EscapeOpImpl(); - } - - private final class EscapeOpImpl extends EscapeOp { - - @Override - public ResolvedJavaType type() { - return type; - } - - @Override - public EscapeField[] fields() { - return virtualObject.fields(); - } + return new EscapeOp() { - @Override - public ValueNode[] fieldState() { - return values.toArray(new ValueNode[values.size()]); - } + @Override + public ValueNode[] fieldState() { + return values.toArray(new ValueNode[values.size()]); + } - @Override - public void beforeUpdate(Node usage) { - throw new UnsupportedOperationException("MaterializeNode can only be escape analyzed using partial escape analysis"); - } - - @Override - public int updateState(VirtualObjectNode node, Node current, Map fieldIndex, ValueNode[] fieldState) { - throw new UnsupportedOperationException("MaterializeNode can only be escape analyzed using partial escape analysis"); - } + @Override + public VirtualObjectNode virtualObject(int virtualId) { + return virtualObject; + } + }; } } diff -r bced4f3a4174 -r 6ad5bf2efb5e 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 Fri Sep 14 15:16:50 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java Fri Sep 14 15:26:57 2012 +0200 @@ -22,14 +22,10 @@ */ package com.oracle.graal.nodes.java; -import java.util.*; - 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.*; -import com.oracle.graal.nodes.util.*; import com.oracle.graal.nodes.virtual.*; /** @@ -50,6 +46,7 @@ /** * Constructs a new NewArrayNode. + * * @param length the node that produces the length for this allocation */ protected NewArrayNode(ResolvedJavaType elementType, ValueNode length, boolean fillContents) { @@ -73,6 +70,7 @@ /** * Gets the element type of the array. + * * @return the element type of the array */ public ResolvedJavaType elementType() { @@ -93,72 +91,27 @@ @Override public EscapeOp getEscapeOp() { - Constant constantLength = length().asConstant(); - if (constantLength != null && constantLength.asInt() >= 0 && constantLength.asInt() < MaximumEscapeAnalysisArrayLength) { - return new EscapeOpImpl(); - } else { - return null; - } - } - - private final class EscapeOpImpl extends EscapeOp { - - @Override - public ResolvedJavaType type() { - return elementType.arrayOf(); - } + if (length().asConstant() != null) { + final int constantLength = length().asConstant().asInt(); + if (constantLength >= 0 && constantLength < MaximumEscapeAnalysisArrayLength) { + return new EscapeOp() { - @Override - public EscapeField[] fields() { - int constantLength = dimension(0).asConstant().asInt(); - EscapeField[] fields = new EscapeField[constantLength]; - for (int i = 0; i < constantLength; i++) { - Integer representation = i; - fields[i] = new EscapeField(Integer.toString(i), representation, elementType()); - } - return fields; - } + @Override + public ValueNode[] fieldState() { + ValueNode[] state = new ValueNode[constantLength]; + for (int i = 0; i < constantLength; i++) { + state[i] = ConstantNode.defaultForKind(elementType().kind(), graph()); + } + return state; + } - @Override - public ValueNode[] fieldState() { - ValueNode[] state = new ValueNode[dimension(0).asConstant().asInt()]; - for (int i = 0; i < state.length; i++) { - state[i] = ConstantNode.defaultForKind(elementType().kind(), graph()); - } - return state; - } - - @Override - public void beforeUpdate(Node usage) { - if (usage instanceof ArrayLengthNode) { - ArrayLengthNode x = (ArrayLengthNode) usage; - StructuredGraph graph = (StructuredGraph) graph(); - x.replaceAtUsages(dimension(0)); - graph.removeFixed(x); - } else { - beforeUpdate(NewArrayNode.this, usage); + @Override + public VirtualObjectNode virtualObject(int virtualId) { + return new VirtualArrayNode(virtualId, elementType, constantLength); + } + }; } } - - @Override - public int updateState(VirtualObjectNode virtualObject, Node current, Map fieldIndex, ValueNode[] fieldState) { - if (current instanceof AccessIndexedNode) { - AccessIndexedNode x = (AccessIndexedNode) current; - if (GraphUtil.unProxify(x.array()) == virtualObject) { - int index = ((AccessIndexedNode) current).index().asConstant().asInt(); - StructuredGraph graph = (StructuredGraph) x.graph(); - if (current instanceof LoadIndexedNode) { - x.replaceAtUsages(fieldState[index]); - graph.removeFixed(x); - } else if (current instanceof StoreIndexedNode) { - fieldState[index] = ((StoreIndexedNode) x).value(); - graph.removeFixed(x); - return index; - } - } - } - return -1; - } - + return null; } } diff -r bced4f3a4174 -r 6ad5bf2efb5e 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 Fri Sep 14 15:16:50 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java Fri Sep 14 15:26:57 2012 +0200 @@ -29,7 +29,6 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; -import com.oracle.graal.nodes.util.*; import com.oracle.graal.nodes.virtual.*; /** @@ -43,6 +42,7 @@ /** * Constructs a NewInstanceNode. + * * @param type the class being allocated */ public NewInstanceNode(ResolvedJavaType type, boolean fillContents) { @@ -53,6 +53,7 @@ /** * Gets the instance class being allocated by this node. + * * @return the instance class allocated */ public ResolvedJavaType instanceClass() { @@ -73,76 +74,39 @@ gen.visitNewInstance(this); } - @Override - public EscapeOp getEscapeOp() { - return instanceClass == null ? null : new EscapeOpImpl(); - } - - private final class EscapeOpImpl extends EscapeOp { - - @Override - public ResolvedJavaType type() { - return instanceClass(); - } - - private void fillEscapeFields(ResolvedJavaType type, List escapeFields) { - if (type != null) { - fillEscapeFields(type.superType(), escapeFields); - JavaField[] declaredFields = type.declaredFields(); - assert declaredFields != null : "the runtime must specify the declared fields of that type"; - for (JavaField field : declaredFields) { - escapeFields.add(new EscapeField(field.name(), field, field.type())); - } + private void fillEscapeFields(ResolvedJavaType type, List escapeFields) { + if (type != null) { + fillEscapeFields(type.superType(), escapeFields); + for (ResolvedJavaField field : type.declaredFields()) { + escapeFields.add(field); } } - - @Override - public EscapeField[] fields() { - assert !instanceClass().isArrayClass(); - List escapeFields = new ArrayList<>(); - fillEscapeFields(instanceClass(), escapeFields); - return escapeFields.toArray(new EscapeField[escapeFields.size()]); - } + } - @Override - public ValueNode[] fieldState() { - EscapeField[] fields = fields(); - ValueNode[] state = new ValueNode[fields.length]; - for (int i = 0; i < state.length; i++) { - state[i] = ConstantNode.defaultForKind(fields[i].type().kind(), graph()); - } - return state; - } + @Override + public EscapeOp getEscapeOp() { + if (instanceClass != null) { + assert !instanceClass().isArrayClass(); + List escapeFields = new ArrayList<>(); + fillEscapeFields(instanceClass(), escapeFields); + final ResolvedJavaField[] fields = escapeFields.toArray(new ResolvedJavaField[escapeFields.size()]); + return new EscapeOp() { - @Override - public void beforeUpdate(Node usage) { - if (usage instanceof RegisterFinalizerNode) { - RegisterFinalizerNode x = (RegisterFinalizerNode) usage; - ((StructuredGraph) x.graph()).removeFixed(x); - } else { - super.beforeUpdate(NewInstanceNode.this, usage); - } - } + @Override + public ValueNode[] fieldState() { + ValueNode[] state = new ValueNode[fields.length]; + for (int i = 0; i < state.length; i++) { + state[i] = ConstantNode.defaultForKind(fields[i].type().kind(), graph()); + } + return state; + } - @Override - public int updateState(VirtualObjectNode node, Node current, Map fieldIndex, ValueNode[] fieldState) { - if (current instanceof AccessFieldNode) { - AccessFieldNode x = (AccessFieldNode) current; - if (GraphUtil.unProxify(x.object()) == node) { - int field = fieldIndex.get(x.field()); - StructuredGraph graph = (StructuredGraph) x.graph(); - if (current instanceof LoadFieldNode) { - assert fieldState[field] != null : field + ", " + x.field(); - x.replaceAtUsages(fieldState[field]); - graph.removeFixed(x); - } else if (current instanceof StoreFieldNode) { - fieldState[field] = ((StoreFieldNode) x).value(); - graph.removeFixed(x); - return field; - } + @Override + public VirtualObjectNode virtualObject(int virtualId) { + return new VirtualInstanceNode(virtualId, instanceClass(), fields); } - } - return -1; + }; } + return null; } } diff -r bced4f3a4174 -r 6ad5bf2efb5e graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/EscapeField.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/EscapeField.java Fri Sep 14 15:16:50 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,55 +0,0 @@ -/* - * Copyright (c) 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.spi; - -import com.oracle.graal.api.meta.*; - -public class EscapeField { - - private final String name; - private final Object representation; - private final JavaType type; - - public EscapeField(String name, Object representation, JavaType type) { - this.name = name; - this.representation = representation; - this.type = type; - } - - public String name() { - return name; - } - - public Object representation() { - return representation; - } - - public JavaType type() { - return type; - } - - @Override - public String toString() { - return name(); - } -} diff -r bced4f3a4174 -r 6ad5bf2efb5e graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/EscapeOp.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/EscapeOp.java Fri Sep 14 15:16:50 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/EscapeOp.java Fri Sep 14 15:26:57 2012 +0200 @@ -22,48 +22,16 @@ */ package com.oracle.graal.nodes.spi; -import java.util.*; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.virtual.*; public abstract class EscapeOp { /** - * Returns the type of object that is created by the associated node. - */ - public abstract ResolvedJavaType type(); - - /** - * Returns all the fields that the objects create by the associated node have. - */ - public abstract EscapeField[] fields(); - - /** - * Returns the initial value of all fields, in the same order as {@link #fields()}. + * Returns the initial value of all fields. */ public abstract ValueNode[] fieldState(); - public abstract void beforeUpdate(Node usage); - - protected static void beforeUpdate(Node node, Node usage) { - // IsNullNode and IsTypeNode should have been eliminated by the CanonicalizerPhase, but we can't rely on this - if (usage instanceof IsNullNode) { - IsNullNode x = (IsNullNode) usage; - ((StructuredGraph) x.graph()).replaceFloating(x, ConstantNode.forBoolean(false, node.graph())); - } else if (usage instanceof IsTypeNode) { - IsTypeNode x = (IsTypeNode) usage; - boolean result = ((ValueNode) node).objectStamp().type() == x.type(); - ((StructuredGraph) x.graph()).replaceFloating(x, ConstantNode.forBoolean(result, node.graph())); - } else if (usage instanceof AccessMonitorNode) { - ((AccessMonitorNode) usage).eliminate(); - } - } - - public abstract int updateState(VirtualObjectNode virtualObject, Node current, Map fieldIndex, ValueNode[] fieldState); + public abstract VirtualObjectNode virtualObject(int virtualId); } diff -r bced4f3a4174 -r 6ad5bf2efb5e 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 Fri Sep 14 15:16:50 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/BoxedVirtualObjectNode.java Fri Sep 14 15:26:57 2012 +0200 @@ -31,14 +31,31 @@ public class BoxedVirtualObjectNode extends VirtualObjectNode implements LIRLowerable, Node.ValueNumberable { @Input ValueNode unboxedValue; + private final ResolvedJavaType type; - public BoxedVirtualObjectNode(int id, ResolvedJavaType type, ValueNode unboxedValue) { - super(id, type, new EscapeField[1]); + public BoxedVirtualObjectNode(int virtualId, ResolvedJavaType type, ValueNode unboxedValue) { + super(virtualId); + this.type = type; this.unboxedValue = unboxedValue; } - public ValueNode getUnboxedValue() { return unboxedValue; } + + @Override + public ResolvedJavaType type() { + return type; + } + + @Override + public int entryCount() { + return 1; + } + + @Override + public Object fieldName(int index) { + assert index == 0; + return "value"; + } } diff -r bced4f3a4174 -r 6ad5bf2efb5e graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualArrayNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualArrayNode.java Fri Sep 14 15:26:57 2012 +0200 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2011, 2012, 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.api.meta.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.spi.*; + +@NodeInfo(nameTemplate = "VirtualArray {p#componentType/s}[{p#length}]") +public class VirtualArrayNode extends VirtualObjectNode { + + private final ResolvedJavaType componentType; + private final int length; + + public VirtualArrayNode(int virtualId, ResolvedJavaType componentType, int length) { + super(virtualId); + this.componentType = componentType; + this.length = length; + } + + @Override + public ResolvedJavaType type() { + return componentType.arrayOf(); + } + + public ResolvedJavaType componentType() { + return componentType; + } + + @Override + public int entryCount() { + return length; + } + + @Override + public void generate(LIRGeneratorTool gen) { + // nothing to do... + } + + @Override + public String toString(Verbosity verbosity) { + if (verbosity == Verbosity.Name) { + return super.toString(Verbosity.Name) + " " + componentType.name() + "[" + length + "]"; + } else { + return super.toString(verbosity); + } + } + + @Override + public Object fieldName(int index) { + return "[" + index + "]"; + } +} diff -r bced4f3a4174 -r 6ad5bf2efb5e graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualInstanceNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualInstanceNode.java Fri Sep 14 15:26:57 2012 +0200 @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2011, 2012, 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 java.util.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; + +@NodeInfo(nameTemplate = "VirtualInstance {p#type}") +public class VirtualInstanceNode extends VirtualObjectNode { + + private final ResolvedJavaType type; + private final ResolvedJavaField[] fields; + private final HashMap fieldMap = new HashMap<>(); + + public VirtualInstanceNode(int virtualId, ResolvedJavaType type, ResolvedJavaField[] fields) { + super(virtualId); + this.type = type; + this.fields = fields; + for (int i = 0; i < fields.length; i++) { + fieldMap.put(fields[i], i); + } + } + + @Override + public ResolvedJavaType type() { + return type; + } + + @Override + public int entryCount() { + return fields.length; + } + + public ResolvedJavaField field(int index) { + return fields[index]; + } + + @Override + public String toString(Verbosity verbosity) { + if (verbosity == Verbosity.Name) { + return super.toString(Verbosity.Name) + " " + type.name(); + } else { + return super.toString(verbosity); + } + } + + @Override + public Object fieldName(int index) { + return fields[index].name(); + } + + public int fieldIndex(ResolvedJavaField field) { + Integer index = fieldMap.get(field); + return index == null ? -1 : index; + } +} diff -r bced4f3a4174 -r 6ad5bf2efb5e 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 Fri Sep 14 15:16:50 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java Fri Sep 14 15:26:57 2012 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2012, 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 @@ -29,22 +29,21 @@ import com.oracle.graal.nodes.type.*; @NodeInfo(nameTemplate = "VirtualObject {p#type}") -public class VirtualObjectNode extends FloatingNode implements LIRLowerable { +public abstract class VirtualObjectNode extends FloatingNode implements LIRLowerable { + + private final int virtualId; - @SuppressWarnings("unused") - private final int id; - private final ResolvedJavaType type; - private final EscapeField[] fields; - - public VirtualObjectNode(int id, ResolvedJavaType type, EscapeField[] fields) { + public VirtualObjectNode(int virtualId) { super(StampFactory.virtual()); - this.id = id; - this.type = type; - this.fields = fields; + this.virtualId = virtualId; } - public ResolvedJavaType type() { - return type; + public abstract ResolvedJavaType type(); + + public abstract int entryCount(); + + public int virtualId() { + return virtualId; } @Override @@ -52,16 +51,5 @@ // nothing to do... } - @Override - public String toString(Verbosity verbosity) { - if (verbosity == Verbosity.Name) { - return super.toString(Verbosity.Name) + " " + type.name(); - } else { - return super.toString(verbosity); - } - } - - public EscapeField[] fields() { - return fields; - } + public abstract Object fieldName(int i); } diff -r bced4f3a4174 -r 6ad5bf2efb5e 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 Fri Sep 14 15:16:50 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectState.java Fri Sep 14 15:26:57 2012 +0200 @@ -41,13 +41,13 @@ public VirtualObjectState(VirtualObjectNode object, ValueNode[] fieldValues) { super(object); - assert object.fields().length == fieldValues.length; + assert object.entryCount() == fieldValues.length; this.fieldValues = new NodeInputList<>(this, fieldValues); } private VirtualObjectState(VirtualObjectNode object, List fieldValues) { super(object); - assert object.fields().length == fieldValues.size(); + assert object.entryCount() == fieldValues.size(); this.fieldValues = new NodeInputList<>(this, fieldValues); }