Search in sources :

Example 1 with PointsToAnalysisMethod

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);
            }
        }
    }
}
Also used : ArrayList(java.util.ArrayList) DebugContext(org.graalvm.compiler.debug.DebugContext) InvokeTypeFlow(com.oracle.graal.pointsto.flow.InvokeTypeFlow) ConvertDeoptimizeToGuardPhase(org.graalvm.compiler.loop.phases.ConvertDeoptimizeToGuardPhase) PointsToAnalysisMethod(com.oracle.graal.pointsto.meta.PointsToAnalysisMethod) AnalysisMethod(com.oracle.graal.pointsto.meta.AnalysisMethod) PointsToAnalysisMethod(com.oracle.graal.pointsto.meta.PointsToAnalysisMethod) StructuredGraph(org.graalvm.compiler.nodes.StructuredGraph) DeoptimizeOnExceptionPhase(org.graalvm.compiler.truffle.compiler.phases.DeoptimizeOnExceptionPhase) MethodCallTargetNode(org.graalvm.compiler.nodes.java.MethodCallTargetNode)

Example 2 with PointsToAnalysisMethod

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
}
Also used : PointsToAnalysisMethod(com.oracle.graal.pointsto.meta.PointsToAnalysisMethod) AnalysisType(com.oracle.graal.pointsto.meta.AnalysisType) AnalysisMethod(com.oracle.graal.pointsto.meta.AnalysisMethod) PointsToAnalysisMethod(com.oracle.graal.pointsto.meta.PointsToAnalysisMethod) TypeState(com.oracle.graal.pointsto.typestate.TypeState) AnalysisField(com.oracle.graal.pointsto.meta.AnalysisField) NativeImagePointsToAnalysis(com.oracle.svm.hosted.analysis.NativeImagePointsToAnalysis) CEntryPoint(org.graalvm.nativeimage.c.function.CEntryPoint)

Aggregations

AnalysisMethod (com.oracle.graal.pointsto.meta.AnalysisMethod)2 PointsToAnalysisMethod (com.oracle.graal.pointsto.meta.PointsToAnalysisMethod)2 InvokeTypeFlow (com.oracle.graal.pointsto.flow.InvokeTypeFlow)1 AnalysisField (com.oracle.graal.pointsto.meta.AnalysisField)1 AnalysisType (com.oracle.graal.pointsto.meta.AnalysisType)1 TypeState (com.oracle.graal.pointsto.typestate.TypeState)1 NativeImagePointsToAnalysis (com.oracle.svm.hosted.analysis.NativeImagePointsToAnalysis)1 ArrayList (java.util.ArrayList)1 DebugContext (org.graalvm.compiler.debug.DebugContext)1 ConvertDeoptimizeToGuardPhase (org.graalvm.compiler.loop.phases.ConvertDeoptimizeToGuardPhase)1 StructuredGraph (org.graalvm.compiler.nodes.StructuredGraph)1 MethodCallTargetNode (org.graalvm.compiler.nodes.java.MethodCallTargetNode)1 DeoptimizeOnExceptionPhase (org.graalvm.compiler.truffle.compiler.phases.DeoptimizeOnExceptionPhase)1 CEntryPoint (org.graalvm.nativeimage.c.function.CEntryPoint)1