use of org.graalvm.compiler.truffle.compiler.nodes.asserts.NeverPartOfCompilationNode 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.truffle.compiler.nodes.asserts.NeverPartOfCompilationNode in project graal by oracle.
the class Target_com_oracle_truffle_api_interop_java_ObjectProxyHandler method handleNeverPartOfCompilation.
private boolean handleNeverPartOfCompilation(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode messageNode) {
String message = "CompilerAsserts.neverPartOfCompilation()";
if (messageNode != null && messageNode.isConstant()) {
message = messageNode.asConstant().toValueString();
}
NeverPartOfCompilationNode neverPartOfCompilation = b.add(new NeverPartOfCompilationNode(message));
if (Options.TruffleCheckNeverPartOfCompilation.getValue()) {
if (neverPartOfCompilation.stateAfter().getMethod().getDeclaringClass().equals(targetMethod.getDeclaringClass())) {
/* Ignore internal use from another method in CompilerAsserts class. */
} else {
CallTreeNode callerNode = ((RuntimeBytecodeParser) b).getCallTreeNode();
CallTreeNode calleeNode = new CallTreeNode(targetMethod, targetMethod, callerNode, callerNode.getLevel() + 1, GraalFeature.buildSourceReference(neverPartOfCompilation.stateAfter()));
neverPartOfCompilationViolations.add(calleeNode);
}
}
return true;
}
use of org.graalvm.compiler.truffle.compiler.nodes.asserts.NeverPartOfCompilationNode in project graal by oracle.
the class Target_com_oracle_truffle_api_interop_java_ObjectProxyHandler method beforeCompilation.
@Override
public void beforeCompilation(BeforeCompilationAccess config) {
BeforeCompilationAccessImpl access = (BeforeCompilationAccessImpl) config;
if (GraalFeature.Options.PrintRuntimeCompileMethods.getValue() && blacklistViolations.size() > 0) {
System.out.println();
System.out.println("=== Found " + blacklistViolations.size() + " compilation blacklist violations ===");
System.out.println();
for (GraalFeature.CallTreeNode node : blacklistViolations) {
System.out.println("Blacklisted method");
System.out.println(node.getImplementationMethod().format(" %H.%n(%p)"));
System.out.println("called from");
for (GraalFeature.CallTreeNode cur = node; cur != null; cur = cur.getParent()) {
System.out.println(" " + cur.getSourceReference());
}
}
}
if (warnViolations.size() > 0) {
/*
* It is enough to print one warning message with one stack trace. Take the shortest
* stack trace.
*/
GraalFeature.CallTreeNode printNode = null;
int printLength = Integer.MAX_VALUE;
for (GraalFeature.CallTreeNode warnNode : warnViolations) {
int warnLength = 0;
for (GraalFeature.CallTreeNode cur = warnNode; cur != null; cur = cur.getParent()) {
warnLength++;
}
if (warnLength < printLength) {
printNode = warnNode;
printLength = warnLength;
}
}
System.out.println("WARNING: suspicious method reachable for runtime compilation: " + printNode.getImplementationMethod().format("%H.%n(%p)"));
System.out.println("Check the complete tree of reachable methods using the option " + GraalFeature.Options.PrintRuntimeCompileMethods.getDescriptor().getFieldName());
System.out.println("Suspicious method is called from");
for (GraalFeature.CallTreeNode cur = printNode; cur != null; cur = cur.getParent()) {
System.out.println(" " + cur.getSourceReference());
}
}
if (neverPartOfCompilationViolations.size() > 0) {
System.out.println("ERROR: CompilerAsserts.neverPartOfCompilation reachable for runtime compilation from " + neverPartOfCompilationViolations.size() + " places:");
for (GraalFeature.CallTreeNode neverPartOfCompilationNode : neverPartOfCompilationViolations) {
System.out.println("called from");
for (GraalFeature.CallTreeNode cur = neverPartOfCompilationNode; cur != null; cur = cur.getParent()) {
System.out.println(" " + cur.getSourceReference());
}
}
throw VMError.shouldNotReachHere("CompilerAsserts.neverPartOfCompilation reachable for runtime compilation");
}
if (Options.TruffleCheckFrameImplementation.getValue() && useTruffleCompiler()) {
/*
* Check that only one Frame implementation is seen as instantiated by the static
* analysis. That allows de-virtualization of all calls to Frame methods in the
* interpreter.
*
* The DefaultTruffleRuntime uses multiple Frame implementations (DefaultVirtualFrame,
* DefaultMaterializedFrame, ReadOnlyFrame) to detect wrong usages of the Frame API, so
* we can only check when running with compilation enabled.
*/
Optional<? extends ResolvedJavaType> optionalFrameType = access.getMetaAccess().optionalLookupJavaType(Frame.class);
if (optionalFrameType.isPresent()) {
HostedType frameType = (HostedType) optionalFrameType.get();
Set<HostedType> implementations = new HashSet<>();
collectImplementations(frameType, implementations);
if (implementations.size() > 1) {
throw UserError.abort("More than one implementation of " + Frame.class.getTypeName() + " found. For performance reasons, Truffle languages must not provide new implementations, and instead only use the single implementation provided by the Truffle runtime. " + "To disable this check, add " + SubstrateOptionsParser.commandArgument(Options.TruffleCheckFrameImplementation, "-") + " to the native-image command line. " + "Found classes: " + implementations.stream().map(m -> m.toJavaName(true)).collect(Collectors.joining(", ")));
} else {
assert implementations.size() == 0 || implementations.iterator().next() == frameType.getSingleImplementor();
}
}
}
}
use of org.graalvm.compiler.truffle.compiler.nodes.asserts.NeverPartOfCompilationNode 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");
}
}
});
}
Aggregations