use of org.graalvm.compiler.truffle.common.TruffleCompilationTask 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.register(new RequiredInvocationPlugin("inInterpreter") {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
b.addPush(JavaKind.Boolean, ConstantNode.forBoolean(false));
return true;
}
});
r.register(new RequiredInvocationPlugin("hasNextTier") {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
if (!canDelayIntrinsification && b.getGraph().getCancellable() instanceof TruffleCompilationTask) {
TruffleCompilationTask task = (TruffleCompilationTask) b.getGraph().getCancellable();
b.addPush(JavaKind.Boolean, ConstantNode.forBoolean(task.hasNextTier()));
return true;
}
return false;
}
});
r.register(new RequiredInvocationPlugin("inCompiledCode") {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
b.addPush(JavaKind.Boolean, ConstantNode.forBoolean(true));
return true;
}
});
r.register(new RequiredInvocationPlugin("inCompilationRoot") {
@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.register(new RequiredInvocationPlugin("transferToInterpreter") {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
b.add(new DeoptimizeNode(DeoptimizationAction.None, DeoptimizationReason.TransferToInterpreter));
return true;
}
});
r.register(new RequiredInvocationPlugin("transferToInterpreterAndInvalidate") {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
b.add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TransferToInterpreter));
return true;
}
});
r.register(new RequiredInvocationPlugin("interpreterOnly", Runnable.class) {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode arg) {
return true;
}
});
r.register(new RequiredInvocationPlugin("interpreterOnly", Callable.class) {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode arg) {
return true;
}
});
r.register(new RequiredInvocationPlugin("injectBranchProbability", double.class, boolean.class) {
@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.register(new RequiredInvocationPlugin("bailout", String.class) {
@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.register(new RequiredInvocationPlugin("isCompilationConstant", Object.class) {
@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.register(new RequiredInvocationPlugin("isPartialEvaluationConstant", Object.class) {
@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.register(new RequiredInvocationPlugin("materialize", Object.class) {
@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.register(new RequiredInvocationPlugin("ensureVirtualized", Object.class) {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode object) {
b.add(new EnsureVirtualizedNode(object, false));
return true;
}
});
r.register(new RequiredInvocationPlugin("ensureVirtualizedHere", Object.class) {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode object) {
b.add(new EnsureVirtualizedNode(object, true));
return true;
}
});
for (JavaKind kind : JavaKind.values()) {
if ((kind.isPrimitive() && kind != JavaKind.Void) || kind == JavaKind.Object) {
Class<?> javaClass = getJavaClass(kind);
r.register(new RequiredInlineOnlyInvocationPlugin("blackhole", javaClass) {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) {
b.add(new BlackholeNode(value));
return true;
}
});
}
}
r.register(new RequiredInvocationPlugin("castExact", Object.class, Class.class) {
@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, true));
}
return true;
}
});
r.register(new RequiredInvocationPlugin("isExact", Object.class, Class.class) {
@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, false, true));
b.addPush(JavaKind.Boolean, b.append(new ConditionalNode(condition)));
return true;
}
});
}
use of org.graalvm.compiler.truffle.common.TruffleCompilationTask in project graal by oracle.
the class TruffleBoundaryExceptionsTest method testExceptionOnTruffleBoundaryDeoptsOnce.
@Test
@SuppressWarnings("try")
public void testExceptionOnTruffleBoundaryDeoptsOnce() {
class DeoptCountingExceptionOverBoundaryRootNode extends RootNode {
protected DeoptCountingExceptionOverBoundaryRootNode() {
super(null);
}
int deoptCounter = 0;
int catchCounter = 0;
int interpretCount = 0;
@Override
public Object execute(VirtualFrame frame) {
boolean startedCompiled = CompilerDirectives.inCompiledCode();
if (!startedCompiled) {
interpretCount++;
}
try {
throwExceptionBoundary();
} catch (RuntimeException e) {
catchCounter++;
}
if (startedCompiled && CompilerDirectives.inInterpreter()) {
deoptCounter++;
}
return null;
}
@CompilerDirectives.TruffleBoundary
public void throwExceptionBoundary() {
throw new RuntimeException();
}
}
final int[] compilationCount = { 0 };
GraalTruffleRuntimeListener listener = new GraalTruffleRuntimeListener() {
@Override
public void onCompilationStarted(OptimizedCallTarget target, TruffleCompilationTask task) {
compilationCount[0]++;
}
};
setupContext("engine.InvalidationReprofileCount", "0", "engine.MultiTier", "false");
DeoptCountingExceptionOverBoundaryRootNode rootNode = new DeoptCountingExceptionOverBoundaryRootNode();
final OptimizedCallTarget outerTarget = (OptimizedCallTarget) rootNode.getCallTarget();
final int compilationThreshold = outerTarget.getOptionValue(SingleTierCompilationThreshold);
for (int i = 0; i < compilationThreshold; i++) {
outerTarget.call();
}
// deoptimizes immediately due to the exception
assertEquals("Incorrect number of deopts detected!", 1, rootNode.deoptCounter);
assertNotCompiled(outerTarget);
// recompile with exception branch
outerTarget.call();
assertCompiled(outerTarget);
runtime.addListener(listener);
try {
final int execCount = 10;
for (int i = 0; i < execCount; i++) {
outerTarget.call();
}
final int totalExecutions = compilationThreshold + 1 + execCount;
assertEquals("Incorrect number of catch block executions", totalExecutions, rootNode.catchCounter);
assertEquals("Incorrect number of interpreted executions", compilationThreshold - 1, rootNode.interpretCount);
assertEquals("Incorrect number of deopts detected!", 1, rootNode.deoptCounter);
assertEquals("Compilation happened!", 0, compilationCount[0]);
} finally {
runtime.removeListener(listener);
}
}
use of org.graalvm.compiler.truffle.common.TruffleCompilationTask in project graal by oracle.
the class IsolateAwareTruffleCompiler method doCompile0.
@CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class)
@CEntryPointOptions(publishAs = CEntryPointOptions.Publish.NotPublished)
private static ClientHandle<String> doCompile0(@SuppressWarnings("unused") @CEntryPoint.IsolateThreadContext CompilerIsolateThread context, ClientIsolateThread client, ImageHeapRef<SubstrateTruffleCompiler> delegateRef, ClientHandle<TruffleCompilationIdentifier> compilationIdentifierHandle, ClientHandle<SubstrateCompilableTruffleAST> compilableHandle, ClientHandle<byte[]> encodedOptionsHandle, int encodedOptionsLength, ClientHandle<TruffleCompilationTask> taskHandle, ClientHandle<IsolatedEventContext> eventContextHandle, boolean firstCompilation) {
IsolatedCompileContext.set(new IsolatedCompileContext(client));
try {
SubstrateTruffleCompiler delegate = ImageHeapObjects.deref(delegateRef);
Map<String, Object> options = decodeOptions(client, encodedOptionsHandle, encodedOptionsLength);
IsolatedCompilableTruffleAST compilable = new IsolatedCompilableTruffleAST(compilableHandle);
delegate.initialize(options, compilable, firstCompilation);
TruffleCompilation compilation = new IsolatedCompilationIdentifier(compilationIdentifierHandle, compilable);
TruffleCompilationTask task = null;
if (taskHandle.notEqual(IsolatedHandles.nullHandle())) {
task = new IsolatedTruffleCompilationTask(taskHandle);
}
TruffleCompilerListener listener = null;
if (eventContextHandle.notEqual(IsolatedHandles.nullHandle())) {
listener = new IsolatedTruffleCompilerEventForwarder(eventContextHandle);
}
delegate.doCompile(null, compilation, options, task, listener);
// no exception
return IsolatedHandles.nullHandle();
} catch (Throwable t) {
StringWriter writer = new StringWriter();
t.printStackTrace(new PrintWriter(writer));
return IsolatedCompileContext.get().createStringInClient(writer.toString());
} finally {
/*
* Compilation isolate do not use a dedicated reference handler thread, so we trigger
* the reference handling manually when a compilation finishes.
*/
Heap.getHeap().doReferenceHandling();
IsolatedCompileContext.set(null);
}
}
use of org.graalvm.compiler.truffle.common.TruffleCompilationTask in project graal by oracle.
the class GraalTruffleRuntime method doCompile.
protected final void doCompile(TruffleDebugContext debug, OptimizedCallTarget callTarget, TruffleCompilationTask task) {
Objects.requireNonNull(callTarget, "Cannot compile null call target.");
Objects.requireNonNull(task, "Compilation task required.");
List<OptimizedCallTarget> oldBlockCompilations = callTarget.blockCompilations;
if (oldBlockCompilations != null) {
for (OptimizedCallTarget blockTarget : oldBlockCompilations) {
if (blockTarget.isValid()) {
continue;
}
listeners.onCompilationQueued(blockTarget, task.tier());
int nodeCount = blockTarget.getNonTrivialNodeCount();
if (nodeCount > callTarget.engine.getEngineOptions().get(PolyglotCompilerOptions.PartialBlockMaximumSize)) {
listeners.onCompilationDequeued(blockTarget, null, "Partial block is too big to be compiled.", task.tier());
continue;
}
compileImpl(debug, blockTarget, task);
}
}
compileImpl(debug, callTarget, task);
if (oldBlockCompilations == null && callTarget.blockCompilations != null) {
// retry with block compilations
((CompilationTask) task).reset();
listeners.onCompilationQueued(callTarget, task.tier());
doCompile(callTarget, task);
}
}
use of org.graalvm.compiler.truffle.common.TruffleCompilationTask in project graal by oracle.
the class AgnosticInliningPhaseTest method runLanguageAgnosticInliningPhase.
protected StructuredGraph runLanguageAgnosticInliningPhase(OptimizedCallTarget callTarget) {
final PartialEvaluator partialEvaluator = getTruffleCompiler(callTarget).getPartialEvaluator();
final CompilationIdentifier compilationIdentifier = new CompilationIdentifier() {
@Override
public String toString(Verbosity verbosity) {
return "";
}
};
final PartialEvaluator.Request request = partialEvaluator.new Request(callTarget.getOptionValues(), getDebugContext(), callTarget, partialEvaluator.rootForCallTarget(callTarget), compilationIdentifier, getSpeculationLog(), new TruffleCompilerImpl.CancellableTruffleCompilationTask(new TruffleCompilationTask() {
private TruffleInliningData inlining = new TruffleInlining();
@Override
public boolean isCancelled() {
return false;
}
@Override
public boolean isLastTier() {
return true;
}
@Override
public TruffleInliningData inliningData() {
return inlining;
}
@Override
public boolean hasNextTier() {
return false;
}
}));
final AgnosticInliningPhase agnosticInliningPhase = new AgnosticInliningPhase(partialEvaluator, request);
agnosticInliningPhase.apply(request.graph, getTruffleCompiler(callTarget).getPartialEvaluator().getProviders());
return request.graph;
}
Aggregations