/** * Tries to find an original value of the given node by traversing through proxies and unambiguous * phis. Note that this method will perform an exhaustive search through phis. It is intended to * be used during graph building, when phi nodes aren't yet canonicalized. * * @param proxy The node whose original value should be determined. */ public static ValueNode originalValue(ValueNode proxy) { ValueNode v = proxy; do { if (v instanceof ValueProxy) { v = ((ValueProxy) v).getOriginalValue(); } else if (v instanceof PhiNode) { v = ((PhiNode) v).singleValue(); } else { break; } } while (v != null); // if the simple check fails (this can happen for complicated phi/proxy/phi constructs), we // do an exhaustive search if (v == null) { NodeWorkList worklist = proxy.graph().createNodeWorkList(); worklist.add(proxy); for (Node node : worklist) { if (node instanceof ValueProxy) { worklist.add(((ValueProxy) node).getOriginalValue()); } else if (node instanceof PhiNode) { worklist.addAll(((PhiNode) node).values()); } else { if (v == null) { v = (ValueNode) node; } else { return null; } } } } return v; }
@Override public void setVirtualEntry(State objectState, int index, ValueNode value) { ObjectState obj = (ObjectState) objectState; assert obj != null && obj.isVirtual() : "not virtual: " + obj; ObjectState valueState = state.getObjectState(value); ValueNode newValue = value; if (valueState == null) { newValue = getReplacedValue(value); assert obj.getEntry(index) == null || obj.getEntry(index).kind() == newValue.kind() || (isObjectEntry(obj.getEntry(index)) && isObjectEntry(newValue)); } else { if (valueState.getState() != EscapeState.Virtual) { newValue = valueState.getMaterializedValue(); assert newValue.kind() == Kind.Object; } else { newValue = valueState.getVirtualObject(); } assert obj.getEntry(index) == null || isObjectEntry(obj.getEntry(index)); } obj.setEntry(index, newValue); }
/** * Process a node as part of this search. * * @param node the next node encountered in the search * @param worklist if non-null, {@code node} will be added to this list. Otherwise, {@code node} * is treated as a candidate result. * @return true if the search should continue, false if a definitive {@link #result} has been * found */ private boolean process(ValueNode node, NodeWorkList worklist) { if (node.isAlive()) { if (worklist == null) { if (result == null) { // Initial candidate result: continue search result = node; } else if (result != node) { // Conflicts with existing candidate: stop search with null result result = null; return false; } } else { worklist.add(node); } } return true; }
public OriginalValueSearch(ValueNode proxy) { NodeWorkList worklist = proxy.graph().createNodeWorkList(); worklist.add(proxy); for (Node node : worklist) { if (node instanceof LimitedValueProxy) { ValueNode originalValue = ((LimitedValueProxy) node).getOriginalNode(); if (!process(originalValue, worklist)) { return; } } else if (node instanceof PhiNode) { for (Node value : ((PhiNode) node).values()) { if (!process((ValueNode) value, worklist)) { return; } } } else { if (!process((ValueNode) node, null)) { return; } } } }
private static boolean isObjectEntry(ValueNode value) { return value.kind() == Kind.Object || value instanceof VirtualObjectNode; }