use of com.oracle.graal.pointsto.meta.PointsToAnalysisMethod in project graal by oracle.
the class GraphPrepareMetaAccessExtensionProvider method processMethod.
@SuppressWarnings("try")
private void processMethod(CallTreeNode node, Deque<CallTreeNode> worklist, BigBang bb) {
AnalysisMethod method = node.implementationMethod;
assert method.isImplementationInvoked();
if (node.graph == null) {
if (method.getAnnotation(Fold.class) != null || method.getAnnotation(NodeIntrinsic.class) != null) {
throw VMError.shouldNotReachHere("Parsing method annotated with @Fold or @NodeIntrinsic: " + method.format("%H.%n(%p)"));
}
if (!method.allowRuntimeCompilation()) {
throw VMError.shouldNotReachHere("Parsing method that is not available for runtime compilation: " + method.format("%H.%n(%p)"));
}
boolean parse = false;
DebugContext debug = bb.getDebug();
StructuredGraph graph = method.buildGraph(debug, method, hostedProviders, Purpose.PREPARE_RUNTIME_COMPILATION);
if (graph == null) {
if (!method.hasBytecodes()) {
return;
}
parse = true;
graph = new StructuredGraph.Builder(debug.getOptions(), debug, AllowAssumptions.YES).method(method).build();
}
try (DebugContext.Scope scope = debug.scope("RuntimeCompile", graph)) {
if (parse) {
RuntimeGraphBuilderPhase builderPhase = new RuntimeGraphBuilderPhase(hostedProviders, graphBuilderConfig, optimisticOpts, null, hostedProviders.getWordTypes(), node);
builderPhase.apply(graph);
}
if (graph.getNodes(StackValueNode.TYPE).isNotEmpty()) {
/*
* Stack allocated memory is not seen by the deoptimization code, i.e., it is
* not copied in case of deoptimization. Also, pointers to it can be used for
* arbitrary address arithmetic, so we would not know how to update derived
* pointers into stack memory during deoptimization. Therefore, we cannot allow
* methods that allocate stack memory for runtime compilation. To remove this
* limitation, we would need to change how we handle stack allocated memory in
* Graal.
*/
return;
}
CanonicalizerPhase.create().apply(graph, hostedProviders);
if (deoptimizeOnExceptionPredicate != null) {
new DeoptimizeOnExceptionPhase(deoptimizeOnExceptionPredicate).apply(graph);
}
new ConvertDeoptimizeToGuardPhase().apply(graph, hostedProviders);
graphEncoder.prepare(graph);
node.graph = graph;
} catch (Throwable ex) {
debug.handle(ex);
}
}
assert node.graph != null;
List<MethodCallTargetNode> callTargets = node.graph.getNodes(MethodCallTargetNode.TYPE).snapshot();
callTargets.sort((t1, t2) -> Integer.compare(t1.invoke().bci(), t2.invoke().bci()));
for (MethodCallTargetNode targetNode : callTargets) {
AnalysisMethod targetMethod = (AnalysisMethod) targetNode.targetMethod();
PointsToAnalysisMethod callerMethod = (PointsToAnalysisMethod) targetNode.invoke().stateAfter().getMethod();
InvokeTypeFlow invokeFlow = callerMethod.getTypeFlow().getOriginalMethodFlows().getInvoke(targetNode.invoke().bci());
if (invokeFlow == null) {
continue;
}
Collection<AnalysisMethod> allImplementationMethods = invokeFlow.getCallees();
/*
* Eventually we want to remove all invokes that are unreachable, i.e., have no
* implementation. But the analysis is iterative, and we don't know here if we have
* already reached the fixed point. So we only collect unreachable invokes here, and
* remove them after the analysis has finished.
*/
if (allImplementationMethods.size() == 0) {
node.unreachableInvokes.add(targetNode.invoke());
} else {
node.unreachableInvokes.remove(targetNode.invoke());
}
List<AnalysisMethod> implementationMethods = new ArrayList<>();
for (AnalysisMethod implementationMethod : allImplementationMethods) {
/* Filter out all the implementation methods that have already been processed. */
if (!methods.containsKey(implementationMethod)) {
implementationMethods.add(implementationMethod);
}
}
if (implementationMethods.size() > 0) {
/* Sort to make printing order and method discovery order deterministic. */
implementationMethods.sort((m1, m2) -> m1.getQualifiedName().compareTo(m2.getQualifiedName()));
String sourceReference = buildSourceReference(targetNode.invoke().stateAfter());
for (AnalysisMethod implementationMethod : implementationMethods) {
CallTreeNode calleeNode = new CallTreeNode(implementationMethod, targetMethod, node, node.level + 1, sourceReference);
if (includeCalleePredicate.includeCallee(calleeNode, implementationMethods)) {
assert !methods.containsKey(implementationMethod);
methods.put(implementationMethod, calleeNode);
worklist.add(calleeNode);
node.children.add(calleeNode);
objectReplacer.createMethod(implementationMethod);
}
/*
* We must compile all methods which may be called. It may be the case that a
* call target does not reach the compile queue by default, e.g. if it is
* inlined at image generation but not at runtime compilation.
*/
CompilationInfoSupport.singleton().registerForcedCompilation(implementationMethod);
}
}
}
}
use of com.oracle.graal.pointsto.meta.PointsToAnalysisMethod in project graal by oracle.
the class NativeImageGenerator method checkUniverse.
private void checkUniverse() {
if (bb instanceof NativeImagePointsToAnalysis) {
NativeImagePointsToAnalysis bigbang = (NativeImagePointsToAnalysis) this.bb;
/*
* Check that the type states for method parameters and fields are compatible with the
* declared type. This is required for interface types because interfaces are not
* trusted according to the Java language specification, but we trust all interface
* types (see HostedType.isTrustedInterfaceType)
*
* TODO Enable checks for non-interface types too.
*/
for (AnalysisMethod m : aUniverse.getMethods()) {
PointsToAnalysisMethod method = PointsToAnalysis.assertPointsToAnalysisMethod(m);
for (int i = 0; i < method.getTypeFlow().getOriginalMethodFlows().getParameters().length; i++) {
TypeState parameterState = method.getTypeFlow().getParameterTypeState(bigbang, i);
if (parameterState != null) {
AnalysisType declaredType = method.getTypeFlow().getOriginalMethodFlows().getParameter(i).getDeclaredType();
if (declaredType.isInterface()) {
TypeState declaredTypeState = declaredType.getAssignableTypes(true);
parameterState = TypeState.forSubtraction(bigbang, parameterState, declaredTypeState);
if (!parameterState.isEmpty()) {
String methodKey = method.format("%H.%n(%p)");
bigbang.getUnsupportedFeatures().addMessage(methodKey, method, "Parameter " + i + " of " + methodKey + " has declared type " + declaredType.toJavaName(true) + ", with assignable types: " + format(bb, declaredTypeState) + ", which is incompatible with analysis inferred types: " + format(bb, parameterState) + ".");
}
}
}
}
}
for (AnalysisField field : aUniverse.getFields()) {
TypeState state = field.getTypeState();
if (state != null) {
AnalysisType declaredType = field.getType();
if (declaredType.isInterface()) {
TypeState declaredTypeState = declaredType.getAssignableTypes(true);
state = TypeState.forSubtraction(bigbang, state, declaredTypeState);
if (!state.isEmpty()) {
String fieldKey = field.format("%H.%n");
bigbang.getUnsupportedFeatures().addMessage(fieldKey, null, "Field " + fieldKey + " has declared type " + declaredType.toJavaName(true) + ", with assignable types: " + format(bb, declaredTypeState) + ", which is incompatible with analysis inferred types: " + format(bb, state) + ".");
}
}
}
}
}
if (SubstrateOptions.VerifyNamingConventions.getValue()) {
for (AnalysisMethod method : aUniverse.getMethods()) {
if ((method.isInvoked() || method.isReachable()) && method.getAnnotation(Fold.class) == null) {
checkName(method.format("%H.%n(%p)"), method, bb);
}
}
for (AnalysisField field : aUniverse.getFields()) {
if (field.isAccessed()) {
checkName(field.format("%H.%n"), null, bb);
}
}
for (AnalysisType type : aUniverse.getTypes()) {
if (type.isReachable()) {
checkName(type.toJavaName(true), null, bb);
}
}
}
/*
* Entry points use a different calling convention (the native C ABI calling convention), so
* they must not be called from other Java methods.
*/
for (AnalysisMethod method : aUniverse.getMethods()) {
if (method.isEntryPoint()) {
Set<AnalysisMethod> invocations = method.getCallers();
if (invocations.size() > 0) {
String name = method.format("%H.%n(%p)");
StringBuilder msg = new StringBuilder("Native entry point is also called from within Java. Invocations: ");
String sep = "";
for (AnalysisMethod invocation : invocations) {
msg.append(sep).append(invocation.format("%H.%n(%p)"));
sep = ", ";
}
bb.getUnsupportedFeatures().addMessage(name, method, msg.toString());
}
}
}
// the unsupported features are reported after checkUniverse is invoked
}
Aggregations