use of org.graalvm.compiler.nodes.extended.BoxNode in project graal by oracle.
the class TruffleGraphBuilderPlugins method registerCompilerDirectivesPlugins.
public static void registerCompilerDirectivesPlugins(InvocationPlugins plugins, MetaAccessProvider metaAccess, boolean canDelayIntrinsification) {
final ResolvedJavaType compilerDirectivesType = getRuntime().resolveType(metaAccess, "com.oracle.truffle.api.CompilerDirectives");
Registration r = new Registration(plugins, new ResolvedJavaSymbol(compilerDirectivesType));
r.register0("inInterpreter", new InvocationPlugin() {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
b.addPush(JavaKind.Boolean, ConstantNode.forBoolean(false));
return true;
}
});
r.register0("inCompiledCode", new InvocationPlugin() {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
b.addPush(JavaKind.Boolean, ConstantNode.forBoolean(true));
return true;
}
});
r.register0("inCompilationRoot", new InvocationPlugin() {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
GraphBuilderContext.ExternalInliningContext inliningContext = b.getExternalInliningContext();
if (inliningContext != null) {
b.addPush(JavaKind.Boolean, ConstantNode.forBoolean(inliningContext.getInlinedDepth() == 0));
return true;
}
return false;
}
});
r.register0("transferToInterpreter", new InvocationPlugin() {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
b.add(new DeoptimizeNode(DeoptimizationAction.None, DeoptimizationReason.TransferToInterpreter));
return true;
}
});
r.register0("transferToInterpreterAndInvalidate", new InvocationPlugin() {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
b.add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TransferToInterpreter));
return true;
}
});
r.register1("interpreterOnly", Runnable.class, new InvocationPlugin() {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode arg) {
return true;
}
});
r.register1("interpreterOnly", Callable.class, new InvocationPlugin() {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode arg) {
return true;
}
});
r.register2("injectBranchProbability", double.class, boolean.class, new InvocationPlugin() {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode probability, ValueNode condition) {
b.addPush(JavaKind.Boolean, new BranchProbabilityNode(probability, condition));
return true;
}
});
r.register1("bailout", String.class, new InvocationPlugin() {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode message) {
if (canDelayIntrinsification) {
/*
* We do not want to bailout yet, since we are still parsing individual methods
* and constant folding could still eliminate the call to bailout(). However, we
* also want to stop parsing, since we are sure that we will never need the
* graph beyond the bailout point.
*
* Therefore, we manually emit the call to bailout, which will be intrinsified
* later when intrinsifications can no longer be delayed. The call is followed
* by a NeverPartOfCompilationNode, which is a control sink and therefore stops
* any further parsing.
*/
StampPair returnStamp = b.getInvokeReturnStamp(b.getAssumptions());
CallTargetNode callTarget = b.add(new MethodCallTargetNode(InvokeKind.Static, targetMethod, new ValueNode[] { message }, returnStamp, null));
b.add(new InvokeNode(callTarget, b.bci()));
b.add(new NeverPartOfCompilationNode("intrinsification of call to bailout() will abort entire compilation"));
return true;
}
if (message.isConstant()) {
throw b.bailout(message.asConstant().toValueString());
}
throw b.bailout("bailout (message is not compile-time constant, so no additional information is available)");
}
});
r.register1("isCompilationConstant", Object.class, new InvocationPlugin() {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) {
if ((value instanceof BoxNode ? ((BoxNode) value).getValue() : value).isConstant()) {
b.addPush(JavaKind.Boolean, ConstantNode.forBoolean(true));
} else {
b.addPush(JavaKind.Boolean, new IsCompilationConstantNode(value));
}
return true;
}
});
r.register1("isPartialEvaluationConstant", Object.class, new InvocationPlugin() {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) {
if ((value instanceof BoxNode ? ((BoxNode) value).getValue() : value).isConstant()) {
b.addPush(JavaKind.Boolean, ConstantNode.forBoolean(true));
} else if (canDelayIntrinsification) {
return false;
} else {
b.addPush(JavaKind.Boolean, ConstantNode.forBoolean(false));
}
return true;
}
});
r.register1("materialize", Object.class, new InvocationPlugin() {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) {
AllowMaterializeNode materializedValue = b.append(new AllowMaterializeNode(value));
b.add(new ForceMaterializeNode(materializedValue));
return true;
}
});
r.register1("ensureVirtualized", Object.class, new InvocationPlugin() {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode object) {
b.add(new EnsureVirtualizedNode(object, false));
return true;
}
});
r.register1("ensureVirtualizedHere", Object.class, new InvocationPlugin() {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode object) {
b.add(new EnsureVirtualizedNode(object, true));
return true;
}
});
r.register2("castExact", Object.class, Class.class, new InvocationPlugin() {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode object, ValueNode javaClass) {
ValueNode nullCheckedClass = b.addNonNullCast(javaClass);
LogicNode condition = b.append(InstanceOfDynamicNode.create(b.getAssumptions(), b.getConstantReflection(), nullCheckedClass, object, true, true));
if (condition.isTautology()) {
b.addPush(JavaKind.Object, object);
} else {
FixedGuardNode fixedGuard = b.add(new FixedGuardNode(condition, DeoptimizationReason.ClassCastException, DeoptimizationAction.InvalidateReprofile, false));
b.addPush(JavaKind.Object, DynamicPiNode.create(b.getAssumptions(), b.getConstantReflection(), object, fixedGuard, nullCheckedClass, true));
}
return true;
}
});
}
use of org.graalvm.compiler.nodes.extended.BoxNode in project graal by oracle.
the class MethodTypeFlowBuilder method registerUsedElements.
public static void registerUsedElements(BigBang bb, StructuredGraph graph, MethodTypeFlow methodFlow) {
for (Node n : graph.getNodes()) {
if (n instanceof InstanceOfNode) {
InstanceOfNode node = (InstanceOfNode) n;
AnalysisType type = (AnalysisType) node.type().getType();
type.registerAsInTypeCheck();
} else if (n instanceof NewInstanceNode) {
NewInstanceNode node = (NewInstanceNode) n;
AnalysisType type = (AnalysisType) node.instanceClass();
type.registerAsAllocated(node);
} else if (n instanceof NewArrayNode) {
NewArrayNode node = (NewArrayNode) n;
AnalysisType type = ((AnalysisType) node.elementType()).getArrayClass();
type.registerAsAllocated(node);
} else if (n instanceof NewMultiArrayNode) {
NewMultiArrayNode node = (NewMultiArrayNode) n;
AnalysisType type = ((AnalysisType) node.type());
for (int i = 0; i < node.dimensionCount(); i++) {
type.registerAsAllocated(node);
type = type.getComponentType();
}
} else if (n instanceof BoxNode) {
BoxNode node = (BoxNode) n;
AnalysisType type = (AnalysisType) StampTool.typeOrNull(node);
type.registerAsAllocated(node);
} else if (n instanceof LoadFieldNode) {
LoadFieldNode node = (LoadFieldNode) n;
AnalysisField field = (AnalysisField) node.field();
field.registerAsRead(methodFlow);
} else if (n instanceof StoreFieldNode) {
StoreFieldNode node = (StoreFieldNode) n;
AnalysisField field = (AnalysisField) node.field();
field.registerAsWritten(methodFlow);
} else if (n instanceof StoreIndexedNode) {
StoreIndexedNode node = (StoreIndexedNode) n;
AnalysisType arrayType = (AnalysisType) StampTool.typeOrNull(node.array());
if (arrayType != null) {
assert arrayType.isArray();
arrayType.getComponentType().registerAsInTypeCheck();
}
} else if (n instanceof BytecodeExceptionNode) {
BytecodeExceptionNode node = (BytecodeExceptionNode) n;
AnalysisType type = bb.getMetaAccess().lookupJavaType(node.getExceptionClass());
type.registerAsInHeap();
} else if (n instanceof ConstantNode) {
ConstantNode cn = (ConstantNode) n;
if (cn.hasUsages() && cn.asJavaConstant().getJavaKind() == JavaKind.Object && cn.asJavaConstant().isNonNull()) {
assert StampTool.isExactType(cn);
AnalysisType type = (AnalysisType) StampTool.typeOrNull(cn);
type.registerAsInHeap();
}
} else if (n instanceof ForeignCallNode) {
ForeignCallNode node = (ForeignCallNode) n;
registerForeignCall(bb, node.getDescriptor());
} else if (n instanceof UnaryMathIntrinsicNode) {
UnaryMathIntrinsicNode node = (UnaryMathIntrinsicNode) n;
registerForeignCall(bb, node.getOperation().foreignCallDescriptor);
} else if (n instanceof BinaryMathIntrinsicNode) {
BinaryMathIntrinsicNode node = (BinaryMathIntrinsicNode) n;
registerForeignCall(bb, node.getOperation().foreignCallDescriptor);
}
}
}
use of org.graalvm.compiler.nodes.extended.BoxNode in project graal by oracle.
the class TruffleGraphBuilderPlugins method registerCompilerAssertsPlugins.
public static void registerCompilerAssertsPlugins(InvocationPlugins plugins, MetaAccessProvider metaAccess, boolean canDelayIntrinsification) {
final ResolvedJavaType compilerAssertsType = getRuntime().resolveType(metaAccess, "com.oracle.truffle.api.CompilerAsserts");
Registration r = new Registration(plugins, new ResolvedJavaSymbol(compilerAssertsType));
r.register1("partialEvaluationConstant", Object.class, new InvocationPlugin() {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) {
ValueNode curValue = value;
if (curValue instanceof BoxNode) {
BoxNode boxNode = (BoxNode) curValue;
curValue = boxNode.getValue();
}
if (curValue.isConstant()) {
return true;
} else if (canDelayIntrinsification) {
return false;
} else {
StringBuilder sb = new StringBuilder();
sb.append(curValue);
if (curValue instanceof ValuePhiNode) {
ValuePhiNode valuePhi = (ValuePhiNode) curValue;
sb.append(" (");
for (Node n : valuePhi.inputs()) {
sb.append(n);
sb.append("; ");
}
sb.append(")");
}
value.getDebug().dump(DebugContext.VERBOSE_LEVEL, value.graph(), "Graph before bailout at node %s", sb);
throw b.bailout("Partial evaluation did not reduce value to a constant, is a regular compiler node: " + sb);
}
}
});
r.register0("neverPartOfCompilation", new InvocationPlugin() {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
b.add(new NeverPartOfCompilationNode("CompilerAsserts.neverPartOfCompilation()"));
return true;
}
});
r.register1("neverPartOfCompilation", String.class, new InvocationPlugin() {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode message) {
if (message.isConstant()) {
String messageString = message.asConstant().toValueString();
b.add(new NeverPartOfCompilationNode(messageString));
return true;
} else {
throw b.bailout("message for never part of compilation is non-constant");
}
}
});
}
use of org.graalvm.compiler.nodes.extended.BoxNode in project graal by oracle.
the class MethodTypeFlowBuilder method apply.
protected void apply() {
// assert method.getAnnotation(Fold.class) == null : method;
if (method.getAnnotation(NodeIntrinsic.class) != null) {
graph.getDebug().log("apply MethodTypeFlow on node intrinsic %s", method);
AnalysisType returnType = (AnalysisType) method.getSignature().getReturnType(method.getDeclaringClass());
if (returnType.getJavaKind() == JavaKind.Object) {
/*
* This is a method used in a snippet, so most likely the return value does not
* matter at all. However, some methods return an object, and the snippet continues
* to work with the object. So pretend that this method returns an object of the
* exact return type.
*/
TypeFlow<?> returnTypeFlow = methodFlow.getResultFlow().getDeclaredType().getTypeFlow(this.bb, true);
returnTypeFlow = new ProxyTypeFlow(null, returnTypeFlow);
FormalReturnTypeFlow resultFlow = new FormalReturnTypeFlow(null, returnType, method);
returnTypeFlow.addOriginalUse(this.bb, resultFlow);
methodFlow.addMiscEntry(returnTypeFlow);
methodFlow.setResult(resultFlow);
}
return;
}
if (!parse()) {
return;
}
this.bb.getUnsupportedFeatures().checkMethod(method, graph);
processedNodes = new NodeBitMap(graph);
TypeFlowsOfNodes typeFlows = new TypeFlowsOfNodes();
for (Node n : graph.getNodes()) {
if (n instanceof ParameterNode) {
ParameterNode node = (ParameterNode) n;
if (node.getStackKind() == JavaKind.Object) {
TypeFlowBuilder<?> paramBuilder = TypeFlowBuilder.create(bb, node, FormalParamTypeFlow.class, () -> {
boolean isStatic = Modifier.isStatic(method.getModifiers());
int index = node.index();
FormalParamTypeFlow parameter;
if (!isStatic && index == 0) {
AnalysisType paramType = method.getDeclaringClass();
parameter = new FormalReceiverTypeFlow(node, paramType, method);
} else {
int offset = isStatic ? 0 : 1;
AnalysisType paramType = (AnalysisType) method.getSignature().getParameterType(index - offset, method.getDeclaringClass());
parameter = new FormalParamTypeFlow(node, paramType, method, index);
}
methodFlow.setParameter(index, parameter);
return parameter;
});
typeFlowGraphBuilder.checkFormalParameterBuilder(paramBuilder);
typeFlows.add(node, paramBuilder);
}
} else if (n instanceof BoxNode) {
BoxNode node = (BoxNode) n;
Object key = uniqueKey(node);
BytecodeLocation boxSite = bb.analysisPolicy().createAllocationSite(bb, key, methodFlow.getMethod());
AnalysisType type = (AnalysisType) StampTool.typeOrNull(node);
TypeFlowBuilder<?> boxBuilder = TypeFlowBuilder.create(bb, node, BoxTypeFlow.class, () -> {
BoxTypeFlow boxFlow = new BoxTypeFlow(node, type, boxSite);
methodFlow.addAllocation(boxFlow);
return boxFlow;
});
typeFlows.add(node, boxBuilder);
}
for (Node input : n.inputs()) {
/*
* TODO change the handling of constants so that the SourceTypeFlow is created on
* demand, with the optimization that only one SourceTypeFlow is created ever for
* every distinct object (using, e.g., caching in a global IdentityHashMap).
*/
if (input instanceof ConstantNode && !typeFlows.contains((ConstantNode) input)) {
ConstantNode node = (ConstantNode) input;
if (node.asJavaConstant().isNull()) {
TypeFlowBuilder<SourceTypeFlow> sourceBuilder = TypeFlowBuilder.create(bb, node, SourceTypeFlow.class, () -> {
SourceTypeFlow constantSource = new SourceTypeFlow(node, TypeState.forNull());
methodFlow.addSource(constantSource);
return constantSource;
});
typeFlows.add(node, sourceBuilder);
} else if (node.asJavaConstant().getJavaKind() == JavaKind.Object) {
/*
* TODO a SubstrateObjectConstant wrapping a PrimitiveConstant has kind
* equals to Object. Do we care about the effective value of these primitive
* constants in the analysis?
*/
assert StampTool.isExactType(node);
AnalysisType type = (AnalysisType) StampTool.typeOrNull(node);
assert type.isInstantiated();
TypeFlowBuilder<SourceTypeFlow> sourceBuilder = TypeFlowBuilder.create(bb, node, SourceTypeFlow.class, () -> {
SourceTypeFlow constantSource = new SourceTypeFlow(node, TypeState.forConstant(this.bb, node.asJavaConstant(), type));
methodFlow.addSource(constantSource);
return constantSource;
});
typeFlows.add(node, sourceBuilder);
}
}
}
}
// Propagate the type flows through the method's graph
new NodeIterator(graph.start(), typeFlows).apply();
/* Prune the method graph. Eliminate nodes with no uses. */
typeFlowGraphBuilder.build();
/*
* Make sure that all existing InstanceOfNodes are registered even when only used as an
* input of a conditional.
*/
for (Node n : graph.getNodes()) {
if (n instanceof InstanceOfNode) {
InstanceOfNode instanceOf = (InstanceOfNode) n;
markFieldsUsedInComparison(instanceOf.getValue());
} else if (n instanceof ObjectEqualsNode) {
ObjectEqualsNode compareNode = (ObjectEqualsNode) n;
markFieldsUsedInComparison(compareNode.getX());
markFieldsUsedInComparison(compareNode.getY());
}
}
}
Aggregations