package com.oracle.svm.hosted.substitute;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.java.FrameStateBuilder;
import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind;
import org.graalvm.compiler.nodes.ConstantNode;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.UnwindNode;
import org.graalvm.compiler.nodes.ValueNode;
import com.oracle.graal.pointsto.meta.HostedProviders;
import com.oracle.svm.core.annotate.Delete;
import com.oracle.svm.core.meta.SubstrateObjectConstant;
import com.oracle.svm.core.option.SubstrateOptionsParser;
import com.oracle.svm.core.util.VMError;
import com.oracle.svm.hosted.annotation.CustomSubstitutionMethod;
import com.oracle.svm.hosted.phases.HostedGraphKit;
import jdk.vm.ci.meta.ResolvedJavaMethod;
public class DeletedMethod extends CustomSubstitutionMethod {
public static final String NATIVE_MESSAGE = String.format(
"Native method. If you intend to use the Java Native Interface (JNI), specify %1$s+JNI and see also %1$sJNIConfigurationFiles=<path> (use %1$s+PrintFlags for details)",
SubstrateOptionsParser.HOSTED_OPTION_PREFIX);
private final Delete deleteAnnotation;
public DeletedMethod(ResolvedJavaMethod original, Delete deleteAnnotation) {
super(original);
this.deleteAnnotation = deleteAnnotation;
}
@Override
public Annotation[] getAnnotations() {
return AnnotatedField.appendAnnotationTo(original.getAnnotations(), deleteAnnotation);
}
@Override
public Annotation[] getDeclaredAnnotations() {
return AnnotatedField.appendAnnotationTo(original.getDeclaredAnnotations(), deleteAnnotation);
}
@Override
public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
if (annotationClass.isInstance(deleteAnnotation)) {
return annotationClass.cast(deleteAnnotation);
}
return original.getAnnotation(annotationClass);
}
public static final Method reportErrorMethod;
static {
try {
reportErrorMethod = VMError.class.getDeclaredMethod("unsupportedFeature", String.class);
} catch (NoSuchMethodException ex) {
throw VMError.shouldNotReachHere(ex);
}
}
@Override
public int getModifiers() {
return original.getModifiers() & ~Modifier.SYNCHRONIZED;
}
@Override
public StructuredGraph buildGraph(DebugContext debug, ResolvedJavaMethod method, HostedProviders providers, Purpose purpose) {
return buildGraph(debug, method, providers, deleteAnnotation.value());
}
public static StructuredGraph buildGraph(DebugContext debug, ResolvedJavaMethod method, HostedProviders providers, String message) {
HostedGraphKit kit = new HostedGraphKit(debug, providers, method);
StructuredGraph graph = kit.getGraph();
FrameStateBuilder state = new FrameStateBuilder(null, method, graph);
state.initializeForMethodStart(null, true, providers.getGraphBuilderPlugins());
int bci = 0;
graph.start().setStateAfter(state.create(bci++, graph.start()));
String msg = AnnotationSubstitutionProcessor.deleteErrorMessage(method, message, false);
ValueNode msgNode = ConstantNode.forConstant(SubstrateObjectConstant.forObject(msg), providers.getMetaAccess(), graph);
ValueNode exceptionNode = kit.createInvokeWithExceptionAndUnwind(providers.getMetaAccess().lookupJavaMethod(reportErrorMethod), InvokeKind.Static, state, bci++, msgNode);
kit.append(new UnwindNode(exceptionNode));
return kit.finalizeGraph();
}
}