All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.oracle.graal.pointsto.ClassInclusionPolicy Maven / Gradle / Ivy

There is a newer version: 24.1.0
Show newest version
/*
 * Copyright (c) 2023, 2023, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package com.oracle.graal.pointsto;

import java.lang.reflect.Executable;
import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Modifier;

import org.graalvm.nativeimage.AnnotationAccess;

import com.oracle.graal.pointsto.meta.AnalysisMethod;

import jdk.graal.compiler.api.replacements.Fold;

/**
 * Policy used to determine which classes, methods and fields need to be included in the image when
 * the {@code IncludeAllFromPath} and/or {@code IncludeAllFromModule} options are specified
 * depending on the configuration.
 */
public abstract class ClassInclusionPolicy {
    protected BigBang bb;
    protected final Object reason;

    public ClassInclusionPolicy(Object reason) {
        this.reason = reason;
    }

    public void setBigBang(BigBang bb) {
        this.bb = bb;
    }

    /**
     * Determine if the given class needs to be included in the image according to the policy.
     */
    public abstract boolean isClassIncluded(Class cls);

    /**
     * Determine if the given method needs to be included in the image according to the policy.
     */
    public boolean isMethodIncluded(Executable method) {
        /*
         * Methods annotated with @Fold should not be included in the base image as they must be
         * inlined. An extension image would inline the method as well and would not use the method
         * from the base image.
         */
        return !AnnotationAccess.isAnnotationPresent(bb.getMetaAccess().lookupJavaMethod(method), Fold.class);
    }

    /**
     * Determine if the given field needs to be included in the image according to the policy.
     */
    public boolean isFieldIncluded(Field field) {
        if (!bb.getHostVM().platformSupported(field)) {
            return false;
        }
        return bb.getHostVM().isFieldIncluded(bb, field);
    }

    /**
     * Includes the given class in the image.
     */
    public void includeClass(Class cls) {
        /*
         * Those classes cannot be registered as allocated as they cannot be instantiated. They are
         * instead registered as reachable as they can still have methods or fields that could be
         * used by an extension image.
         */
        if (Modifier.isAbstract(cls.getModifiers()) || cls.isInterface() || cls.isPrimitive()) {
            bb.getMetaAccess().lookupJavaType(cls).registerAsReachable(reason);
        } else {
            bb.getMetaAccess().lookupJavaType(cls).registerAsInstantiated(reason);
        }
    }

    /**
     * Includes the given method in the image.
     */
    public abstract void includeMethod(Executable method);

    /**
     * Includes the given field in the image.
     */
    public void includeField(Field field) {
        bb.postTask(debug -> bb.addRootField(field));
    }

    /**
     * The analysis for the base layer of a layered image assumes that any method that is reachable
     * using the base java access rules can be an entry point. An upper layer does not have access
     * to the packages from a lower layer. Thus, only the public classes with their public and
     * protected inner classes and methods can be accessed by an upper layer.
     * 

* Protected elements from a final or sealed class cannot be accessed as an upper layer cannot * create a new class that extends the final or sealed class. *

* All the fields are included disregarding access rules as a missing field would cause issues * in the object layout. */ public static class LayeredBaseImageInclusionPolicy extends ClassInclusionPolicy { public LayeredBaseImageInclusionPolicy(Object reason) { super(reason); } @Override public boolean isClassIncluded(Class cls) { Class enclosingClass = cls.getEnclosingClass(); int classModifiers = cls.getModifiers(); if (enclosingClass != null) { return isAccessible(enclosingClass, classModifiers) && isClassIncluded(enclosingClass); } else { return Modifier.isPublic(classModifiers); } } @Override public boolean isMethodIncluded(Executable method) { return !Modifier.isAbstract(method.getModifiers()) && isAccessible(method) && super.isMethodIncluded(method); } @Override public void includeMethod(Executable method) { bb.postTask(debug -> { /* * Non-abstract methods from an abstract class or default methods from an interface * are not registered as implementation invoked by the analysis because their * declaring class cannot be marked as instantiated and AnalysisType.getTypeFlow * only includes instantiated types (see TypeFlow.addObserver). For now, to ensure * those methods are included in the image, they are manually registered as * implementation invoked. */ Class declaringClass = method.getDeclaringClass(); if (!Modifier.isAbstract(method.getModifiers()) && (declaringClass.isInterface() || Modifier.isAbstract(declaringClass.getModifiers()))) { AnalysisMethod analysisMethod = bb.getMetaAccess().lookupJavaMethod(method); analysisMethod.registerAsDirectRootMethod(reason); analysisMethod.registerAsImplementationInvoked(reason); } bb.forcedAddRootMethod(method, false, reason); }); } } /** * The default inclusion policy. Includes all classes and methods. Including all fields causes * issues at the moment, so the same rules as for the {@link LayeredBaseImageInclusionPolicy} * are used. */ public static class DefaultAllInclusionPolicy extends ClassInclusionPolicy { public DefaultAllInclusionPolicy(Object reason) { super(reason); } @Override public boolean isClassIncluded(Class cls) { return true; } @Override public void includeMethod(Executable method) { bb.postTask(debug -> bb.addRootMethod(method, false, reason)); } } protected boolean isAccessible(Member member) { Class cls = member.getDeclaringClass(); int modifiers = member.getModifiers(); return isAccessible(cls, modifiers); } protected boolean isAccessible(Class cls, int modifiers) { return Modifier.isPublic(modifiers) || (!Modifier.isFinal(cls.getModifiers()) && !cls.isSealed() && Modifier.isProtected(modifiers)); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy