package org.graalvm.compiler.nodes.graphbuilderconf;
import static jdk.vm.ci.code.BytecodeFrame.AFTER_BCI;
import static jdk.vm.ci.code.BytecodeFrame.AFTER_EXCEPTION_BCI;
import static jdk.vm.ci.code.BytecodeFrame.BEFORE_BCI;
import static jdk.vm.ci.code.BytecodeFrame.INVALID_FRAMESTATE_BCI;
import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.ROOT_COMPILATION_ENCODING;
import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING;
import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.ROOT_COMPILATION;
import org.graalvm.compiler.api.replacements.MethodSubstitution;
import org.graalvm.compiler.bytecode.BytecodeProvider;
import org.graalvm.compiler.graph.NodeSourcePosition;
import org.graalvm.compiler.nodes.AbstractMergeNode;
import org.graalvm.compiler.nodes.FrameState;
import org.graalvm.compiler.nodes.Invoke;
import org.graalvm.compiler.nodes.LoopExitNode;
import org.graalvm.compiler.nodes.StateSplit;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.java.ExceptionObjectNode;
import jdk.vm.ci.meta.ResolvedJavaMethod;
public class IntrinsicContext {
final ResolvedJavaMethod originalMethod;
final ResolvedJavaMethod intrinsicMethod;
final BytecodeProvider bytecodeProvider;
final CompilationContext compilationContext;
final boolean allowPartialIntrinsicArgumentMismatch;
public IntrinsicContext(ResolvedJavaMethod method, ResolvedJavaMethod intrinsic, BytecodeProvider bytecodeProvider, CompilationContext compilationContext) {
this(method, intrinsic, bytecodeProvider, compilationContext, false);
}
public IntrinsicContext(ResolvedJavaMethod method, ResolvedJavaMethod intrinsic, BytecodeProvider bytecodeProvider, CompilationContext compilationContext,
boolean allowPartialIntrinsicArgumentMismatch) {
this.originalMethod = method;
this.intrinsicMethod = intrinsic;
this.bytecodeProvider = bytecodeProvider;
assert bytecodeProvider != null;
this.compilationContext = compilationContext;
this.allowPartialIntrinsicArgumentMismatch = allowPartialIntrinsicArgumentMismatch;
assert !isCompilationRoot() || method.hasBytecodes() : "Cannot root compile intrinsic for native or abstract method " + method.format("%H.%n(%p)");
assert !method.equals(intrinsic) || method.getAnnotation(MethodSubstitution.class) == null : "method and intrinsic must be different: " + method + " " + intrinsic;
}
public boolean allowPartialIntrinsicArgumentMismatch() {
return allowPartialIntrinsicArgumentMismatch;
}
public ResolvedJavaMethod getOriginalMethod() {
return originalMethod;
}
public ResolvedJavaMethod getIntrinsicMethod() {
return intrinsicMethod;
}
public BytecodeProvider getBytecodeProvider() {
return bytecodeProvider;
}
public boolean isCallToOriginal(ResolvedJavaMethod targetMethod) {
return originalMethod.equals(targetMethod) || intrinsicMethod.equals(targetMethod);
}
private NodeSourcePosition nodeSourcePosition;
public boolean isPostParseInlined() {
return compilationContext.equals(INLINE_AFTER_PARSING);
}
public boolean isCompilationRoot() {
return compilationContext.equals(ROOT_COMPILATION) || compilationContext.equals(ROOT_COMPILATION_ENCODING);
}
public boolean isIntrinsicEncoding() {
return compilationContext.equals(ROOT_COMPILATION_ENCODING);
}
public NodeSourcePosition getNodeSourcePosition() {
return nodeSourcePosition;
}
public void setNodeSourcePosition(NodeSourcePosition position) {
assert nodeSourcePosition == null : "can only be set once";
this.nodeSourcePosition = position;
}
public enum CompilationContext {
INLINE_DURING_PARSING,
INLINE_AFTER_PARSING,
ROOT_COMPILATION,
ROOT_COMPILATION_ENCODING
}
public interface SideEffectsState {
boolean isAfterSideEffect();
Iterable<StateSplit> sideEffects();
void addSideEffect(StateSplit sideEffect);
}
@SuppressWarnings("unused")
public boolean isDeferredInvoke(StateSplit stateSplit) {
return false;
}
public FrameState createFrameState(StructuredGraph graph, SideEffectsState sideEffects, StateSplit forStateSplit, NodeSourcePosition sourcePosition) {
assert forStateSplit != graph.start();
if (forStateSplit.hasSideEffect()) {
if (sideEffects.isAfterSideEffect()) {
FrameState invalid = graph.add(new FrameState(INVALID_FRAMESTATE_BCI));
if (graph.trackNodeSourcePosition()) {
invalid.setNodeSourcePosition(sourcePosition);
}
for (StateSplit lastSideEffect : sideEffects.sideEffects()) {
lastSideEffect.setStateAfter(invalid);
}
}
FrameState frameState;
if (isDeferredInvoke(forStateSplit)) {
frameState = graph.add(new FrameState(INVALID_FRAMESTATE_BCI));
} else {
sideEffects.addSideEffect(forStateSplit);
if (forStateSplit instanceof ExceptionObjectNode) {
frameState = graph.add(new FrameState(AFTER_EXCEPTION_BCI, (ExceptionObjectNode) forStateSplit));
} else {
frameState = graph.add(new FrameState(AFTER_BCI));
}
}
if (graph.trackNodeSourcePosition()) {
frameState.setNodeSourcePosition(sourcePosition);
}
return frameState;
} else {
if (forStateSplit instanceof AbstractMergeNode || forStateSplit instanceof LoopExitNode) {
if (sideEffects.isAfterSideEffect()) {