use of org.graalvm.compiler.nodes.virtual.VirtualInstanceNode in project graal by oracle.
the class StoreFieldNode method virtualize.
@Override
public void virtualize(VirtualizerTool tool) {
ValueNode alias = tool.getAlias(object());
if (alias instanceof VirtualObjectNode) {
VirtualInstanceNode virtual = (VirtualInstanceNode) alias;
int fieldIndex = virtual.fieldIndex(field());
if (fieldIndex != -1) {
tool.setVirtualEntry(virtual, fieldIndex, value());
tool.delete();
}
}
}
use of org.graalvm.compiler.nodes.virtual.VirtualInstanceNode 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.VirtualInstanceNode in project graal by oracle.
the class VirtualizerToolImpl method setVirtualEntry.
@Override
public boolean setVirtualEntry(VirtualObjectNode virtual, int index, ValueNode value, JavaKind theAccessKind, long offset) {
ObjectState obj = state.getObjectState(virtual);
assert obj.isVirtual() : "not virtual: " + obj;
ValueNode newValue;
JavaKind entryKind = virtual.entryKind(index);
JavaKind accessKind = theAccessKind != null ? theAccessKind : entryKind;
if (value == null) {
newValue = null;
} else {
newValue = closure.getAliasAndResolve(state, value);
}
getDebug().log(DebugContext.DETAILED_LEVEL, "Setting entry %d in virtual object %s %s results in %s", index, virtual.getObjectId(), virtual, state.getObjectState(virtual.getObjectId()));
ValueNode oldValue = getEntry(virtual, index);
boolean canVirtualize = entryKind == accessKind || (entryKind == accessKind.getStackKind() && virtual instanceof VirtualInstanceNode);
if (!canVirtualize) {
if (entryKind == JavaKind.Long && oldValue.getStackKind() == newValue.getStackKind() && oldValue.getStackKind().isPrimitive()) {
/*
* Special case: If the entryKind is long, allow arbitrary kinds as long as a value
* of the same kind is already there. This can only happen if some other node
* initialized the entry with a value of a different kind. One example where this
* happens is the Truffle NewFrameNode.
*/
getDebug().log(DebugContext.DETAILED_LEVEL, "virtualizing %s with primitive of kind %s in long entry ", current, oldValue.getStackKind());
canVirtualize = true;
} else if (entryKind == JavaKind.Int && (accessKind == JavaKind.Long || accessKind == JavaKind.Double) && offset % 8 == 0) {
/*
* Special case: Allow storing a single long or double value into two consecutive
* int slots.
*/
int nextIndex = virtual.entryIndexForOffset(getArrayOffsetProvider(), offset + 4, JavaKind.Int);
if (nextIndex != -1) {
canVirtualize = true;
assert nextIndex == index + 1 : "expected to be sequential";
getDebug().log(DebugContext.DETAILED_LEVEL, "virtualizing %s for double word stored in two ints", current);
}
}
}
if (canVirtualize) {
getDebug().log(DebugContext.DETAILED_LEVEL, "virtualizing %s for entryKind %s and access kind %s", current, entryKind, accessKind);
state.setEntry(virtual.getObjectId(), index, newValue);
if (entryKind == JavaKind.Int) {
if (accessKind.needsTwoSlots()) {
// Storing double word value two int slots
assert virtual.entryKind(index + 1) == JavaKind.Int;
state.setEntry(virtual.getObjectId(), index + 1, getIllegalConstant());
} else if (oldValue.getStackKind() == JavaKind.Double || oldValue.getStackKind() == JavaKind.Long) {
// Splitting double word constant by storing over it with an int
getDebug().log(DebugContext.DETAILED_LEVEL, "virtualizing %s producing second half of double word value %s", current, oldValue);
ValueNode secondHalf = UnpackEndianHalfNode.create(oldValue, false, NodeView.DEFAULT);
addNode(secondHalf);
state.setEntry(virtual.getObjectId(), index + 1, secondHalf);
}
}
if (oldValue.isConstant() && oldValue.asConstant().equals(JavaConstant.forIllegal())) {
// Storing into second half of double, so replace previous value
ValueNode previous = getEntry(virtual, index - 1);
getDebug().log(DebugContext.DETAILED_LEVEL, "virtualizing %s producing first half of double word value %s", current, previous);
ValueNode firstHalf = UnpackEndianHalfNode.create(previous, true, NodeView.DEFAULT);
addNode(firstHalf);
state.setEntry(virtual.getObjectId(), index - 1, firstHalf);
}
return true;
}
// Should only occur if there are mismatches between the entry and access kind
assert entryKind != accessKind;
return false;
}
use of org.graalvm.compiler.nodes.virtual.VirtualInstanceNode in project graal by oracle.
the class DefaultJavaLoweringProvider method lowerCommitAllocationNode.
@SuppressWarnings("try")
protected void lowerCommitAllocationNode(CommitAllocationNode commit, LoweringTool tool) {
StructuredGraph graph = commit.graph();
if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) {
List<AbstractNewObjectNode> recursiveLowerings = new ArrayList<>();
ValueNode[] allocations = new ValueNode[commit.getVirtualObjects().size()];
BitSet omittedValues = new BitSet();
int valuePos = 0;
for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) {
VirtualObjectNode virtual = commit.getVirtualObjects().get(objIndex);
int entryCount = virtual.entryCount();
AbstractNewObjectNode newObject;
try (DebugCloseable nsp = virtual.withNodeSourcePosition()) {
if (virtual instanceof VirtualInstanceNode) {
newObject = graph.add(createNewInstanceFromVirtual(virtual));
} else {
newObject = graph.add(createNewArrayFromVirtual(virtual, ConstantNode.forInt(entryCount, graph)));
}
}
recursiveLowerings.add(newObject);
graph.addBeforeFixed(commit, newObject);
allocations[objIndex] = newObject;
for (int i = 0; i < entryCount; i++) {
ValueNode value = commit.getValues().get(valuePos);
if (value instanceof VirtualObjectNode) {
value = allocations[commit.getVirtualObjects().indexOf(value)];
}
if (value == null) {
omittedValues.set(valuePos);
} else if (!(value.isConstant() && value.asConstant().isDefaultForKind())) {
// Constant.illegal is always the defaultForKind, so it is skipped
JavaKind valueKind = value.getStackKind();
JavaKind entryKind = virtual.entryKind(i);
// Truffle requires some leniency in terms of what can be put where:
assert valueKind.getStackKind() == entryKind.getStackKind() || (valueKind == JavaKind.Long || valueKind == JavaKind.Double || (valueKind == JavaKind.Int && virtual instanceof VirtualArrayNode));
AddressNode address = null;
BarrierType barrierType = null;
if (virtual instanceof VirtualInstanceNode) {
ResolvedJavaField field = ((VirtualInstanceNode) virtual).field(i);
long offset = fieldOffset(field);
if (offset >= 0) {
address = createOffsetAddress(graph, newObject, offset);
barrierType = fieldInitializationBarrier(entryKind);
}
} else {
address = createOffsetAddress(graph, newObject, arrayBaseOffset(entryKind) + i * arrayScalingFactor(entryKind));
barrierType = arrayInitializationBarrier(entryKind);
}
if (address != null) {
WriteNode write = new WriteNode(address, LocationIdentity.init(), implicitStoreConvert(graph, entryKind, value), barrierType);
graph.addAfterFixed(newObject, graph.add(write));
}
}
valuePos++;
}
}
valuePos = 0;
for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) {
VirtualObjectNode virtual = commit.getVirtualObjects().get(objIndex);
int entryCount = virtual.entryCount();
ValueNode newObject = allocations[objIndex];
for (int i = 0; i < entryCount; i++) {
if (omittedValues.get(valuePos)) {
ValueNode value = commit.getValues().get(valuePos);
assert value instanceof VirtualObjectNode;
ValueNode allocValue = allocations[commit.getVirtualObjects().indexOf(value)];
if (!(allocValue.isConstant() && allocValue.asConstant().isDefaultForKind())) {
assert virtual.entryKind(i) == JavaKind.Object && allocValue.getStackKind() == JavaKind.Object;
AddressNode address;
BarrierType barrierType;
if (virtual instanceof VirtualInstanceNode) {
VirtualInstanceNode virtualInstance = (VirtualInstanceNode) virtual;
address = createFieldAddress(graph, newObject, virtualInstance.field(i));
barrierType = BarrierType.IMPRECISE;
} else {
address = createArrayAddress(graph, newObject, virtual.entryKind(i), ConstantNode.forInt(i, graph));
barrierType = BarrierType.PRECISE;
}
if (address != null) {
WriteNode write = new WriteNode(address, LocationIdentity.init(), implicitStoreConvert(graph, JavaKind.Object, allocValue), barrierType);
graph.addBeforeFixed(commit, graph.add(write));
}
}
}
valuePos++;
}
}
finishAllocatedObjects(tool, commit, allocations);
graph.removeFixed(commit);
for (AbstractNewObjectNode recursiveLowering : recursiveLowerings) {
recursiveLowering.lower(tool);
}
}
}
use of org.graalvm.compiler.nodes.virtual.VirtualInstanceNode in project graal by oracle.
the class PartialEvaluator method postPartialEvaluation.
private static void postPartialEvaluation(final StructuredGraph graph) {
NeverPartOfCompilationNode.verifyNotFoundIn(graph);
for (AllowMaterializeNode materializeNode : graph.getNodes(AllowMaterializeNode.TYPE).snapshot()) {
materializeNode.replaceAtUsages(materializeNode.getFrame());
graph.removeFixed(materializeNode);
}
TruffleCompilerRuntime rt = TruffleCompilerRuntime.getRuntime();
for (VirtualObjectNode virtualObjectNode : graph.getNodes(VirtualObjectNode.TYPE)) {
if (virtualObjectNode instanceof VirtualInstanceNode) {
VirtualInstanceNode virtualInstanceNode = (VirtualInstanceNode) virtualObjectNode;
ResolvedJavaType type = virtualInstanceNode.type();
if (rt.isValueType(type)) {
virtualInstanceNode.setIdentity(false);
}
}
}
if (!TruffleCompilerOptions.getValue(TruffleInlineAcrossTruffleBoundary)) {
// Do not inline across Truffle boundaries.
for (MethodCallTargetNode mct : graph.getNodes(MethodCallTargetNode.TYPE)) {
InlineInfo inlineInfo = rt.getInlineInfo(mct.targetMethod(), false);
if (!inlineInfo.allowsInlining()) {
mct.invoke().setUseForInlining(false);
}
}
}
}
Aggregations