use of org.graalvm.compiler.core.common.type.ObjectStamp in project graal by oracle.
the class InferStamps method inferStamps.
/**
* Infer the stamps for all Object nodes in the graph, to make the stamps as precise as
* possible. For example, this propagates the word-type through phi functions. To handle phi
* functions at loop headers, the stamp inference is called until a fix point is reached.
* <p>
* This method can be used when it is needed that stamps are inferred before the first run of
* the canonicalizer. For example, word type rewriting must run before the first run of the
* canonicalizer because many nodes are not prepared to see the word type during
* canonicalization.
*/
public static void inferStamps(StructuredGraph graph) {
/*
* We want to make the stamps more precise. For cyclic phi functions, this means we have to
* ignore the initial stamp because the imprecise stamp would always propagate around the
* cycle. We therefore set the stamp to an illegal stamp, which is automatically ignored
* when the phi function performs the "meet" operator on its input stamps.
*/
for (Node n : graph.getNodes()) {
if (n instanceof ValuePhiNode) {
ValueNode node = (ValueNode) n;
if (node.stamp(NodeView.DEFAULT) instanceof ObjectStamp) {
assert node.stamp(NodeView.DEFAULT).hasValues() : "We assume all Phi and Proxy stamps are legal before the analysis";
node.setStamp(node.stamp(NodeView.DEFAULT).empty());
}
}
}
boolean stampChanged;
// The algorithm is not guaranteed to reach a stable state.
int z = 0;
do {
stampChanged = false;
/*
* We could use GraphOrder.forwardGraph() to process the nodes in a defined order and
* propagate long def-use chains in fewer iterations. However, measurements showed that
* we have few iterations anyway, and the overhead of computing the order is much higher
* than the benefit.
*/
for (Node n : graph.getNodes()) {
if (n instanceof ValueNode) {
ValueNode node = (ValueNode) n;
if (node.stamp(NodeView.DEFAULT) instanceof ObjectStamp) {
stampChanged |= node.inferStamp();
}
}
}
++z;
} while (stampChanged && z < 10000);
/*
* Check that all the illegal stamps we introduced above are correctly replaced with real
* stamps again.
*/
assert checkNoEmptyStamp(graph);
}
use of org.graalvm.compiler.core.common.type.ObjectStamp in project graal by oracle.
the class ObjectStampJoinTest method testJoinInterface1.
private void testJoinInterface1(Class<?> typeA, Class<?> typeI) {
Stamp aNonNull = StampFactory.objectNonNull(getType(typeA));
Stamp i = StampFactory.object(getType(typeI));
Stamp join = join(aNonNull, i);
Assert.assertTrue(join instanceof ObjectStamp);
Assert.assertTrue(((ObjectStamp) join).nonNull());
}
use of org.graalvm.compiler.core.common.type.ObjectStamp in project graal by oracle.
the class CInterfaceEnumTool method createEnumLookupInvoke.
public ValueNode createEnumLookupInvoke(HostedGraphKit kit, ResolvedJavaType enumType, EnumInfo enumInfo, JavaKind parameterKind, ValueNode arg) {
InvokeNode invoke = invokeEnumLookup(kit, CallTargetFactory.from(kit), kit.getFrameState(), kit.bci(), enumInfo, parameterKind, arg);
ObjectStamp resultStamp = StampFactory.object(TypeReference.create(null, enumType), false);
return kit.unique(new PiNode(invoke, resultStamp));
}
use of org.graalvm.compiler.core.common.type.ObjectStamp in project graal by oracle.
the class StrengthenStampsPhase method strengthenStamp.
private Stamp strengthenStamp(ValueNode node, JavaTypeProfile typeProfile) {
ObjectStamp oldStamp = (ObjectStamp) node.stamp(NodeView.DEFAULT);
HostedType oldType = toHosted(oldStamp.type());
if (oldStamp.alwaysNull()) {
/* We cannot make that more precise. */
return oldStamp;
}
boolean nonNull = oldStamp.nonNull() || typeProfile.getNullSeen() == TriState.FALSE;
ProfiledType[] exactTypes = typeProfile.getTypes();
if (exactTypes.length == 1) {
ResolvedJavaType exactType = exactTypes[0].getType();
assert oldType == null || oldType.isAssignableFrom(exactType);
if (!oldStamp.isExactType() || !exactType.equals(oldType) || nonNull != oldStamp.nonNull()) {
TypeReference typeRef = TypeReference.createExactTrusted(toTarget(exactType));
return nonNull ? StampFactory.objectNonNull(typeRef) : StampFactory.object(typeRef);
} else {
return oldStamp;
}
}
if (exactTypes.length == 0) {
if (!nonNull) {
return StampFactory.alwaysNull();
} else {
/*
* The code after the node is unreachable. We just insert a always-failing guard
* after the node and let dead code elimination remove everything after the node.
*/
StructuredGraph graph = node.graph();
FixedWithNextNode insertionPoint;
if (node instanceof ParameterNode) {
/* The whole method is unreachable. */
insertionPoint = graph.start();
} else if (node instanceof InvokeWithExceptionNode) {
/* The invoked method never returns normally (but can throw an exception). */
insertionPoint = ((InvokeWithExceptionNode) node).next();
} else {
insertionPoint = (FixedWithNextNode) node;
}
graph.addAfterFixed(insertionPoint, graph.add(new FixedGuardNode(LogicConstantNode.forBoolean(true, graph), DeoptimizationReason.UnreachedCode, DeoptimizationAction.None, true)));
return oldStamp;
}
}
ResolvedJavaType baseType;
if (oldStamp.isExactType()) {
/* Base type cannot be more precise. */
baseType = oldType;
} else {
assert exactTypes.length > 1;
assert oldType == null || oldType.isAssignableFrom(exactTypes[0].getType());
baseType = exactTypes[0].getType();
for (int i = 1; i < exactTypes.length; i++) {
assert oldType == null || oldType.isAssignableFrom(exactTypes[i].getType());
baseType = baseType.findLeastCommonAncestor(exactTypes[i].getType());
}
if (oldType != null && !oldType.isAssignableFrom(baseType)) {
/*
* When the original stamp is an interface type, we do not want to weaken that type
* with the common base class of all implementation types (which could even be
* java.lang.Object).
*/
baseType = oldType;
}
}
if (!baseType.equals(oldType) || nonNull != oldStamp.nonNull()) {
TypeReference typeRef = TypeReference.createTrustedWithoutAssumptions(toTarget(baseType));
return nonNull ? StampFactory.objectNonNull(typeRef) : StampFactory.object(typeRef);
}
return oldStamp;
}
use of org.graalvm.compiler.core.common.type.ObjectStamp in project graal by oracle.
the class StrengthenStampsPhase method run.
@Override
protected void run(StructuredGraph graph) {
for (Node n : graph.getNodes()) {
if (n instanceof ValueNode && !(n instanceof LimitedValueProxy) && !(n instanceof PhiNode)) {
/*
* The stamp of proxy nodes and phi nodes is inferred automatically, so we do not
* need to improve them.
*/
ValueNode node = (ValueNode) n;
/*
* First ask the node to improve the stamp itself, to incorporate already improved
* input stamps.
*/
node.inferStamp();
Stamp newStamp = strengthen(node.stamp(NodeView.DEFAULT));
if (newStamp != null) {
node.setStamp(newStamp);
}
}
if (n instanceof LoadFieldNode) {
LoadFieldNode node = (LoadFieldNode) n;
updateStamp(node, toHosted(node.field()).getFieldTypeProfile());
} else if (n instanceof InstanceOfNode) {
InstanceOfNode node = (InstanceOfNode) n;
ObjectStamp newStamp = (ObjectStamp) strengthen(node.getCheckedStamp());
if (newStamp != null) {
node.strengthenCheckedStamp(newStamp);
}
} else if (n instanceof PiNode) {
PiNode node = (PiNode) n;
Stamp newStamp = strengthen(node.piStamp());
if (newStamp != null) {
node.strengthenPiStamp(newStamp);
}
}
}
}
Aggregations