use of org.graalvm.compiler.nodes.ParameterNode in project graal by oracle.
the class ReinterpretStampLongToDoubleTest method run.
@Test
public void run() {
ParameterNode param = new ParameterNode(0, StampPair.createSingle(inputStamp));
ValueNode reinterpret = ReinterpretNode.create(JavaKind.Double, param, NodeView.DEFAULT);
reinterpret.inferStamp();
FloatStamp resultStamp = (FloatStamp) reinterpret.stamp(NodeView.DEFAULT);
Assert.assertEquals(Double.SIZE, resultStamp.getBits());
for (long input : interestingLongs) {
double result = Double.longBitsToDouble(input);
if (inputStamp.contains(input) && !resultStamp.contains(result)) {
Assert.fail(String.format("value 0x%x (%f) is in input stamp, but not in result stamp (%s)", input, result, resultStamp));
}
}
}
use of org.graalvm.compiler.nodes.ParameterNode 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.nodes.ParameterNode in project graal by oracle.
the class AssertValueNode method insert.
protected static void insert(ValueNode input, AssertValueNode assertionNode) {
StructuredGraph graph = input.graph();
/* Find the insertion point where we want to add the assertion node. */
FixedWithNextNode insertionPoint;
if (input instanceof ParameterNode) {
insertionPoint = graph.start();
} else if (input instanceof InvokeWithExceptionNode) {
insertionPoint = ((InvokeWithExceptionNode) input).next();
} else if (input instanceof FixedWithNextNode) {
insertionPoint = (FixedWithNextNode) input;
} else {
throw shouldNotReachHere("Node is not fixed: " + input);
}
/*
* When inserting after an invoke that is also a loop exit, a proxy node is inserted between
* the invoke and every usage. We need to be after this proxy node to avoid unschedulable
* graphs.
*/
ProxyNode proxyUsage = null;
boolean otherUsages = false;
for (Node usage : input.usages()) {
if (usage instanceof ProxyNode && ((ProxyNode) usage).proxyPoint() == insertionPoint) {
assert proxyUsage == null : "can have only one proxy";
proxyUsage = (ProxyNode) usage;
} else if (!(usage instanceof FrameState)) {
otherUsages = true;
}
}
assert proxyUsage == null || otherUsages == false : "cannot have other usages when having a proxy usage";
ValueNode assertInput = proxyUsage != null ? proxyUsage : input;
/*
* Replace the object at usages. We do not process usages at the frame state because it
* could be the stateAfter() of the insertion point. Since frame states are not doing
* anything in code, this is not a loss of assertion precision.
*/
for (Node usage : assertInput.usages().snapshot()) {
if (!(usage instanceof FrameState)) {
usage.replaceFirstInput(assertInput, assertionNode);
}
}
/*
* Set the input object of the assertion node, now that all other usages have been replaced.
*/
assertionNode.updateUsages(assertionNode.input, assertInput);
assertionNode.input = assertInput;
/* Insert assertion node in graph. */
graph.addAfterFixed(insertionPoint, assertionNode);
}
use of org.graalvm.compiler.nodes.ParameterNode in project graal by oracle.
the class IntrinsifyMethodHandlesInvocationPlugin method processInvokeWithMethodHandle.
@SuppressWarnings("try")
private void processInvokeWithMethodHandle(GraphBuilderContext b, BytecodeProvider bytecodeProvider, ResolvedJavaMethod methodHandleMethod, ValueNode[] methodHandleArguments) {
Plugins graphBuilderPlugins = new Plugins(((ReplacementsImpl) originalProviders.getReplacements()).getGraphBuilderPlugins());
registerInvocationPlugins(graphBuilderPlugins.getInvocationPlugins(), bytecodeProvider);
graphBuilderPlugins.prependParameterPlugin(new MethodHandlesParameterPlugin(methodHandleArguments));
graphBuilderPlugins.clearInlineInvokePlugins();
graphBuilderPlugins.prependInlineInvokePlugin(new MethodHandlesInlineInvokePlugin());
graphBuilderPlugins.prependNodePlugin(new MethodHandlePlugin(originalProviders.getConstantReflection().getMethodHandleAccess(), false));
/* We do all the word type rewriting because parameters to the lambda can be word types. */
SnippetReflectionProvider originalSnippetReflection = GraalAccess.getOriginalSnippetReflection();
WordOperationPlugin wordOperationPlugin = new WordOperationPlugin(originalSnippetReflection, new WordTypes(originalProviders.getMetaAccess(), FrameAccess.getWordKind()));
graphBuilderPlugins.appendInlineInvokePlugin(wordOperationPlugin);
graphBuilderPlugins.appendTypePlugin(wordOperationPlugin);
graphBuilderPlugins.appendTypePlugin(new TrustedInterfaceTypePlugin());
graphBuilderPlugins.appendNodePlugin(wordOperationPlugin);
GraphBuilderConfiguration graphBuilderConfig = GraphBuilderConfiguration.getSnippetDefault(graphBuilderPlugins);
GraphBuilderPhase.Instance graphBuilder = new GraphBuilderPhase.Instance(originalProviders.getMetaAccess(), originalProviders.getStampProvider(), originalProviders.getConstantReflection(), originalProviders.getConstantFieldProvider(), graphBuilderConfig, OptimisticOptimizations.NONE, null);
DebugContext debug = b.getDebug();
StructuredGraph graph = new StructuredGraph.Builder(b.getOptions(), debug).method(toOriginal(methodHandleMethod)).build();
try (DebugContext.Scope s = debug.scope("IntrinsifyMethodHandles", graph)) {
graphBuilder.apply(graph);
/*
* We do not care about the improved type information from Pi nodes, so we just delete
* them to simplify our graph.
*/
for (PiNode pi : graph.getNodes(PiNode.TYPE)) {
pi.replaceAndDelete(pi.object());
}
/*
* Support for MethodHandle that adapt the input type to a more generic type, i.e., a
* MethodHandle that does a dynamic type check on a parameter.
*/
for (UnaryOpLogicNode node : graph.getNodes().filter(UnaryOpLogicNode.class).filter(v -> v instanceof IsNullNode || v instanceof InstanceOfNode)) {
ValueNode value = node.getValue();
if (value instanceof ParameterNode) {
/*
* We just assume that the InstanceOfNode or IsNullNode are used in an If and
* the true-successor is actually the branch we want. If that assumption is
* wrong, nothing bad happens - we will just continue to report the invocation
* as unsupported because the updated stamp for the parameter will not simplify
* the graph.
*/
if (node instanceof InstanceOfNode) {
InstanceOfNode inst = (InstanceOfNode) node;
TypeReference typeRef = inst.type();
value.setStamp(new ObjectStamp(typeRef.getType(), typeRef.isExact(), !inst.allowsNull(), false));
} else {
assert node instanceof IsNullNode;
ResolvedJavaType type = value.stamp(NodeView.DEFAULT).javaType(originalProviders.getMetaAccess());
value.setStamp(new ObjectStamp(type, false, /* non-null */
true, false));
}
}
}
/*
* The canonicalizer converts unsafe field accesses for get/set method handles back to
* high-level field load and store nodes.
*/
new CanonicalizerPhase().apply(graph, new PhaseContext(originalProviders));
for (FixedGuardNode guard : graph.getNodes(FixedGuardNode.TYPE)) {
if (guard.next() instanceof AccessFieldNode && guard.condition() instanceof IsNullNode && guard.isNegated() && ((IsNullNode) guard.condition()).getValue() == ((AccessFieldNode) guard.next()).object()) {
/*
* Method handles to load and stores fields have null checks. Remove them, since
* the null check is implicitly done by the field access.
*/
GraphUtil.removeFixedWithUnusedInputs(guard);
}
}
debug.dump(DebugContext.VERY_DETAILED_LEVEL, graph, "Final intrinisfication graph");
/*
* After parsing (and recursive inlining during parsing), the graph must contain only
* one invocation (and therefore only one MethodCallTargetNode), plus the parameters,
* constants, start, and return nodes.
*/
Node singleFunctionality = null;
ReturnNode singleReturn = null;
for (Node node : graph.getNodes()) {
if (node == graph.start() || node instanceof ParameterNode || node instanceof ConstantNode || node instanceof FrameState) {
/* Ignore the allowed framework around the nodes we care about. */
continue;
} else if (node instanceof Invoke) {
/* We check the MethodCallTargetNode, so we can ignore the invoke. */
continue;
} else if ((node instanceof MethodCallTargetNode || node instanceof LoadFieldNode || node instanceof StoreFieldNode) && singleFunctionality == null) {
singleFunctionality = node;
continue;
} else if (node instanceof ReturnNode && singleReturn == null) {
singleReturn = (ReturnNode) node;
continue;
}
throw new UnsupportedFeatureException("Invoke with MethodHandle argument could not be reduced to at most a single call: " + methodHandleMethod.format("%H.%n(%p)"));
}
if (singleFunctionality instanceof MethodCallTargetNode) {
MethodCallTargetNode singleCallTarget = (MethodCallTargetNode) singleFunctionality;
assert singleReturn.result() == null || singleReturn.result() == singleCallTarget.invoke();
/*
* Replace the originalTarget with the replacementTarget. Note that the
* replacementTarget node belongs to a different graph than originalTarget, so we
* need to match parameter back to the original graph and allocate a new
* MethodCallTargetNode for the original graph.
*/
ValueNode[] replacedArguments = new ValueNode[singleCallTarget.arguments().size()];
for (int i = 0; i < replacedArguments.length; i++) {
replacedArguments[i] = lookup(b, methodHandleArguments, singleCallTarget.arguments().get(i));
}
b.handleReplacedInvoke(singleCallTarget.invokeKind(), lookup(singleCallTarget.targetMethod()), replacedArguments, false);
} else if (singleFunctionality instanceof LoadFieldNode) {
LoadFieldNode fieldLoad = (LoadFieldNode) singleFunctionality;
b.addPush(b.getInvokeReturnType().getJavaKind(), LoadFieldNode.create(null, lookup(b, methodHandleArguments, fieldLoad.object()), lookup(fieldLoad.field())));
} else if (singleFunctionality instanceof StoreFieldNode) {
StoreFieldNode fieldStore = (StoreFieldNode) singleFunctionality;
b.add(new StoreFieldNode(lookup(b, methodHandleArguments, fieldStore.object()), lookup(fieldStore.field()), lookup(b, methodHandleArguments, fieldStore.value())));
} else if (singleReturn.result() != null) {
/* Replace the invocation with he constant result. */
JavaConstant constantResult = singleReturn.result().asJavaConstant();
assert b.getInvokeReturnType().getJavaKind() == constantResult.getJavaKind();
b.addPush(constantResult.getJavaKind(), ConstantNode.forConstant(lookup(constantResult), universeProviders.getMetaAccess()));
} else {
/* No invoke and no return value, so nothing to do. */
assert b.getInvokeReturnType().getJavaKind() == JavaKind.Void;
}
} catch (Throwable ex) {
throw debug.handle(ex);
}
}
use of org.graalvm.compiler.nodes.ParameterNode in project graal by oracle.
the class ReinterpretStampIntToFloatTest method run.
@Test
public void run() {
ParameterNode param = new ParameterNode(0, StampPair.createSingle(inputStamp));
ValueNode reinterpret = ReinterpretNode.create(JavaKind.Float, param, NodeView.DEFAULT);
reinterpret.inferStamp();
FloatStamp resultStamp = (FloatStamp) reinterpret.stamp(NodeView.DEFAULT);
Assert.assertEquals(Float.SIZE, resultStamp.getBits());
for (int input : interestingInts) {
float result = Float.intBitsToFloat(input);
if (inputStamp.contains(input) && !resultStamp.contains(result)) {
Assert.fail(String.format("value 0x%x (%f) is in input stamp, but not in result stamp (%s)", input, result, resultStamp));
}
}
}
Aggregations