use of org.graalvm.compiler.nodes.virtual.VirtualObjectNode in project graal by oracle.
the class BasicArrayCopyNode method virtualize.
@Override
public void virtualize(VirtualizerTool tool) {
ValueNode sourcePosition = tool.getAlias(getSourcePosition());
ValueNode destinationPosition = tool.getAlias(getDestinationPosition());
ValueNode replacedLength = tool.getAlias(getLength());
if (sourcePosition.isConstant() && destinationPosition.isConstant() && replacedLength.isConstant()) {
int srcPosInt = sourcePosition.asJavaConstant().asInt();
int destPosInt = destinationPosition.asJavaConstant().asInt();
int len = replacedLength.asJavaConstant().asInt();
ValueNode destAlias = tool.getAlias(getDestination());
if (destAlias instanceof VirtualArrayNode) {
VirtualArrayNode destVirtual = (VirtualArrayNode) destAlias;
if (len < 0 || !checkBounds(destPosInt, len, destVirtual)) {
return;
}
ValueNode srcAlias = tool.getAlias(getSource());
if (srcAlias instanceof VirtualObjectNode) {
if (!(srcAlias instanceof VirtualArrayNode)) {
return;
}
VirtualArrayNode srcVirtual = (VirtualArrayNode) srcAlias;
if (destVirtual.componentType().getJavaKind() != srcVirtual.componentType().getJavaKind()) {
return;
}
if (!checkBounds(srcPosInt, len, srcVirtual)) {
return;
}
if (!checkEntryTypes(srcPosInt, len, srcVirtual, destVirtual.type().getComponentType(), tool)) {
return;
}
for (int i = 0; i < len; i++) {
tool.setVirtualEntry(destVirtual, destPosInt + i, tool.getEntry(srcVirtual, srcPosInt + i));
}
tool.delete();
DebugContext debug = getDebug();
if (debug.isLogEnabled()) {
debug.log("virtualized arraycopy(%s, %d, %s, %d, %d)", getSource(), srcPosInt, getDestination(), destPosInt, len);
}
} else {
ResolvedJavaType sourceType = StampTool.typeOrNull(srcAlias);
if (sourceType == null || !sourceType.isArray()) {
return;
}
ResolvedJavaType sourceComponentType = sourceType.getComponentType();
ResolvedJavaType destComponentType = destVirtual.type().getComponentType();
if (!sourceComponentType.equals(destComponentType)) {
return;
}
for (int i = 0; i < len; i++) {
LoadIndexedNode load = new LoadIndexedNode(graph().getAssumptions(), srcAlias, ConstantNode.forInt(i + srcPosInt, graph()), destComponentType.getJavaKind());
tool.addNode(load);
tool.setVirtualEntry(destVirtual, destPosInt + i, load);
}
tool.delete();
}
}
}
}
use of org.graalvm.compiler.nodes.virtual.VirtualObjectNode in project graal by oracle.
the class BasicObjectCloneNode method virtualize.
@Override
public void virtualize(VirtualizerTool tool) {
ValueNode originalAlias = tool.getAlias(getObject());
if (originalAlias instanceof VirtualObjectNode) {
VirtualObjectNode originalVirtual = (VirtualObjectNode) originalAlias;
if (originalVirtual.type().isCloneableWithAllocation()) {
ValueNode[] newEntryState = new ValueNode[originalVirtual.entryCount()];
for (int i = 0; i < newEntryState.length; i++) {
newEntryState[i] = tool.getEntry(originalVirtual, i);
}
VirtualObjectNode newVirtual = originalVirtual.duplicate();
tool.createVirtualObject(newVirtual, newEntryState, Collections.<MonitorIdNode>emptyList(), false);
tool.replaceWithVirtual(newVirtual);
}
} else {
ResolvedJavaType type = getConcreteType(originalAlias.stamp(NodeView.DEFAULT));
if (type != null && !type.isArray()) {
VirtualInstanceNode newVirtual = createVirtualInstanceNode(type, true);
ResolvedJavaField[] fields = newVirtual.getFields();
ValueNode[] state = new ValueNode[fields.length];
final LoadFieldNode[] loads = new LoadFieldNode[fields.length];
for (int i = 0; i < fields.length; i++) {
state[i] = loads[i] = genLoadFieldNode(graph().getAssumptions(), originalAlias, fields[i]);
tool.addNode(loads[i]);
}
tool.createVirtualObject(newVirtual, state, Collections.<MonitorIdNode>emptyList(), false);
tool.replaceWithVirtual(newVirtual);
}
}
}
use of org.graalvm.compiler.nodes.virtual.VirtualObjectNode in project graal by oracle.
the class DebugInfoBuilder method build.
public LIRFrameState build(FrameState topState, LabelRef exceptionEdge) {
assert virtualObjects.size() == 0;
assert objectStates.size() == 0;
assert pendingVirtualObjects.size() == 0;
// collect all VirtualObjectField instances:
FrameState current = topState;
do {
if (current.virtualObjectMappingCount() > 0) {
for (EscapeObjectState state : current.virtualObjectMappings()) {
if (!objectStates.containsKey(state.object())) {
if (!(state instanceof MaterializedObjectState) || ((MaterializedObjectState) state).materializedValue() != state.object()) {
objectStates.put(state.object(), state);
}
}
}
}
current = current.outerFrameState();
} while (current != null);
BytecodeFrame frame = computeFrameForState(topState);
VirtualObject[] virtualObjectsArray = null;
if (virtualObjects.size() != 0) {
// fill in the VirtualObject values
VirtualObjectNode vobjNode;
while ((vobjNode = pendingVirtualObjects.poll()) != null) {
VirtualObject vobjValue = virtualObjects.get(vobjNode);
assert vobjValue.getValues() == null;
JavaValue[] values;
JavaKind[] slotKinds;
int entryCount = vobjNode.entryCount();
if (entryCount == 0) {
values = NO_JAVA_VALUES;
slotKinds = NO_JAVA_KINDS;
} else {
values = new JavaValue[entryCount];
slotKinds = new JavaKind[entryCount];
}
if (values.length > 0) {
VirtualObjectState currentField = (VirtualObjectState) objectStates.get(vobjNode);
assert currentField != null;
int pos = 0;
for (int i = 0; i < entryCount; i++) {
ValueNode value = currentField.values().get(i);
if (value == null) {
JavaKind entryKind = vobjNode.entryKind(i);
values[pos] = JavaConstant.defaultForKind(entryKind.getStackKind());
slotKinds[pos] = entryKind.getStackKind();
pos++;
} else if (!value.isConstant() || value.asJavaConstant().getJavaKind() != JavaKind.Illegal) {
values[pos] = toJavaValue(value);
slotKinds[pos] = toSlotKind(value);
pos++;
} else {
assert value.getStackKind() == JavaKind.Illegal;
ValueNode previousValue = currentField.values().get(i - 1);
assert (previousValue != null && previousValue.getStackKind().needsTwoSlots()) : vobjNode + " " + i + " " + previousValue + " " + currentField.values().snapshot();
if (previousValue == null || !previousValue.getStackKind().needsTwoSlots()) {
// Don't allow the IllegalConstant to leak into the debug info
JavaKind entryKind = vobjNode.entryKind(i);
values[pos] = JavaConstant.defaultForKind(entryKind.getStackKind());
slotKinds[pos] = entryKind.getStackKind();
pos++;
}
}
}
if (pos != entryCount) {
values = Arrays.copyOf(values, pos);
slotKinds = Arrays.copyOf(slotKinds, pos);
}
}
assert checkValues(vobjValue.getType(), values, slotKinds);
vobjValue.setValues(values, slotKinds);
}
virtualObjectsArray = new VirtualObject[virtualObjects.size()];
int index = 0;
for (VirtualObject value : virtualObjects.getValues()) {
virtualObjectsArray[index++] = value;
}
virtualObjects.clear();
}
objectStates.clear();
return newLIRFrameState(exceptionEdge, frame, virtualObjectsArray);
}
use of org.graalvm.compiler.nodes.virtual.VirtualObjectNode in project graal by oracle.
the class CanonicalStringGraphPrinter method writeCanonicalGraphString.
protected static void writeCanonicalGraphString(StructuredGraph graph, boolean excludeVirtual, boolean checkConstants, PrintWriter writer) {
StructuredGraph.ScheduleResult scheduleResult = GraphPrinter.getScheduleOrNull(graph);
if (scheduleResult == null) {
return;
}
try {
NodeMap<Integer> canonicalId = graph.createNodeMap();
int nextId = 0;
List<String> constantsLines = null;
if (checkConstants) {
constantsLines = new ArrayList<>();
}
for (Block block : scheduleResult.getCFG().getBlocks()) {
writer.print("Block ");
writer.print(block);
writer.print(" ");
if (block == scheduleResult.getCFG().getStartBlock()) {
writer.print("* ");
}
writer.print("-> ");
for (Block successor : block.getSuccessors()) {
writer.print(successor);
writer.print(" ");
}
writer.println();
for (Node node : scheduleResult.getBlockToNodesMap().get(block)) {
if (node instanceof ValueNode && node.isAlive()) {
if (!excludeVirtual || !(node instanceof VirtualObjectNode || node instanceof ProxyNode || node instanceof FullInfopointNode)) {
if (node instanceof ConstantNode) {
if (constantsLines != null) {
String name = node.toString(Verbosity.Name);
String str = name + (excludeVirtual ? "" : " (" + filteredUsageCount(node) + ")");
constantsLines.add(str);
}
} else {
int id;
if (canonicalId.get(node) != null) {
id = canonicalId.get(node);
} else {
id = nextId++;
canonicalId.set(node, id);
}
String name = node.getClass().getSimpleName();
writer.print(" ");
writer.print(id);
writer.print("|");
writer.print(name);
if (!excludeVirtual) {
writer.print(" (");
writer.print(filteredUsageCount(node));
writer.print(")");
}
writer.println();
}
}
}
}
}
if (constantsLines != null) {
writer.print(constantsLines.size());
writer.println(" constants:");
Collections.sort(constantsLines);
for (String s : constantsLines) {
writer.println(s);
}
}
} catch (Throwable t) {
writer.println();
t.printStackTrace(writer);
}
}
use of org.graalvm.compiler.nodes.virtual.VirtualObjectNode in project graal by oracle.
the class GraphOrder method assertSchedulableGraph.
/**
* This method schedules the graph and makes sure that, for every node, all inputs are available
* at the position where it is scheduled. This is a very expensive assertion.
*/
public static boolean assertSchedulableGraph(final StructuredGraph graph) {
assert graph.getGuardsStage() != GuardsStage.AFTER_FSA : "Cannot use the BlockIteratorClosure after FrameState Assignment, HIR Loop Data Structures are no longer valid.";
try {
final SchedulePhase schedulePhase = new SchedulePhase(SchedulingStrategy.LATEST_OUT_OF_LOOPS, true);
final EconomicMap<LoopBeginNode, NodeBitMap> loopEntryStates = EconomicMap.create(Equivalence.IDENTITY);
schedulePhase.apply(graph, false);
final ScheduleResult schedule = graph.getLastSchedule();
BlockIteratorClosure<NodeBitMap> closure = new BlockIteratorClosure<NodeBitMap>() {
@Override
protected List<NodeBitMap> processLoop(Loop<Block> loop, NodeBitMap initialState) {
return ReentrantBlockIterator.processLoop(this, loop, initialState).exitStates;
}
@Override
protected NodeBitMap processBlock(final Block block, final NodeBitMap currentState) {
final List<Node> list = graph.getLastSchedule().getBlockToNodesMap().get(block);
/*
* A stateAfter is not valid directly after its associated state split, but
* right before the next fixed node. Therefore a pending stateAfter is kept that
* will be checked at the correct position.
*/
FrameState pendingStateAfter = null;
for (final Node node : list) {
if (node instanceof ValueNode) {
FrameState stateAfter = node instanceof StateSplit ? ((StateSplit) node).stateAfter() : null;
if (node instanceof FullInfopointNode) {
stateAfter = ((FullInfopointNode) node).getState();
}
if (pendingStateAfter != null && node instanceof FixedNode) {
pendingStateAfter.applyToNonVirtual(new NodeClosure<Node>() {
@Override
public void apply(Node usage, Node nonVirtualNode) {
assert currentState.isMarked(nonVirtualNode) || nonVirtualNode instanceof VirtualObjectNode || nonVirtualNode instanceof ConstantNode : nonVirtualNode + " not available at virtualstate " + usage + " before " + node + " in block " + block + " \n" + list;
}
});
pendingStateAfter = null;
}
if (node instanceof AbstractMergeNode) {
// phis aren't scheduled, so they need to be added explicitly
currentState.markAll(((AbstractMergeNode) node).phis());
if (node instanceof LoopBeginNode) {
// remember the state at the loop entry, it's restored at exits
loopEntryStates.put((LoopBeginNode) node, currentState.copy());
}
} else if (node instanceof ProxyNode) {
assert false : "proxy nodes should not be in the schedule";
} else if (node instanceof LoopExitNode) {
if (graph.hasValueProxies()) {
for (ProxyNode proxy : ((LoopExitNode) node).proxies()) {
for (Node input : proxy.inputs()) {
if (input != proxy.proxyPoint()) {
assert currentState.isMarked(input) : input + " not available at " + proxy + " in block " + block + "\n" + list;
}
}
}
// loop contents are only accessible via proxies at the exit
currentState.clearAll();
currentState.markAll(loopEntryStates.get(((LoopExitNode) node).loopBegin()));
}
// Loop proxies aren't scheduled, so they need to be added
// explicitly
currentState.markAll(((LoopExitNode) node).proxies());
} else {
for (Node input : node.inputs()) {
if (input != stateAfter) {
if (input instanceof FrameState) {
((FrameState) input).applyToNonVirtual(new VirtualState.NodeClosure<Node>() {
@Override
public void apply(Node usage, Node nonVirtual) {
assert currentState.isMarked(nonVirtual) : nonVirtual + " not available at " + node + " in block " + block + "\n" + list;
}
});
} else {
assert currentState.isMarked(input) || input instanceof VirtualObjectNode || input instanceof ConstantNode : input + " not available at " + node + " in block " + block + "\n" + list;
}
}
}
}
if (node instanceof AbstractEndNode) {
AbstractMergeNode merge = ((AbstractEndNode) node).merge();
for (PhiNode phi : merge.phis()) {
ValueNode phiValue = phi.valueAt((AbstractEndNode) node);
assert phiValue == null || currentState.isMarked(phiValue) || phiValue instanceof ConstantNode : phiValue + " not available at phi " + phi + " / end " + node + " in block " + block;
}
}
if (stateAfter != null) {
assert pendingStateAfter == null;
pendingStateAfter = stateAfter;
}
currentState.mark(node);
}
}
if (pendingStateAfter != null) {
pendingStateAfter.applyToNonVirtual(new NodeClosure<Node>() {
@Override
public void apply(Node usage, Node nonVirtualNode) {
assert currentState.isMarked(nonVirtualNode) || nonVirtualNode instanceof VirtualObjectNode || nonVirtualNode instanceof ConstantNode : nonVirtualNode + " not available at virtualstate " + usage + " at end of block " + block + " \n" + list;
}
});
}
return currentState;
}
@Override
protected NodeBitMap merge(Block merge, List<NodeBitMap> states) {
NodeBitMap result = states.get(0);
for (int i = 1; i < states.size(); i++) {
result.intersect(states.get(i));
}
return result;
}
@Override
protected NodeBitMap getInitialState() {
NodeBitMap ret = graph.createNodeBitMap();
ret.markAll(graph.getNodes().filter(ConstantNode.class));
return ret;
}
@Override
protected NodeBitMap cloneState(NodeBitMap oldState) {
return oldState.copy();
}
};
ReentrantBlockIterator.apply(closure, schedule.getCFG().getStartBlock());
} catch (Throwable t) {
graph.getDebug().handle(t);
}
return true;
}
Aggregations