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

org.qbicc.plugin.reachability.ReachabilityFactsSetup Maven / Gradle / Ivy

package org.qbicc.plugin.reachability;

import org.qbicc.context.CompilationContext;
import org.qbicc.facts.Condition;
import org.qbicc.facts.Facts;
import org.qbicc.facts.core.ExecutableReachabilityFacts;
import org.qbicc.graph.atomic.AccessModes;
import org.qbicc.interpreter.VmObject;
import org.qbicc.type.PhysicalObjectType;
import org.qbicc.type.ReferenceType;
import org.qbicc.type.definition.LoadedTypeDefinition;
import org.qbicc.type.definition.element.ConstructorElement;
import org.qbicc.type.definition.element.ExecutableElement;
import org.qbicc.type.definition.element.InstanceFieldElement;
import org.qbicc.type.definition.element.InstanceMethodElement;

/**
 * Core facts utility class.
 */
public final class ReachabilityFactsSetup {
    private ReachabilityFactsSetup() {}

    public static void setupAdd(CompilationContext ctxt) {
        Facts facts = Facts.get(ctxt);
        setupReachability(facts);
    }

    public static void setupAnalyze(CompilationContext ctxt) {
        Facts facts = Facts.get(ctxt);
        setupReachability(facts);
        setupValidate(facts);
    }

    public static void setupLower(CompilationContext ctxt) {
        Facts facts = Facts.get(ctxt);
        setupReachability(facts);
        setupValidate(facts);
    }

    public static void setupGenerate(CompilationContext ctxt) {
        Facts facts = Facts.get(ctxt);
        setupReachability(facts);
        setupValidate(facts);
    }

    private static void setupReachability(final Facts facts) {
        facts.registerInlineAction(Condition.when(TypeReachabilityFacts.IS_INSTANTIATED), ReachabilityFactsSetup::markEachMethodAsInstantiated);
        facts.registerInlineAction(Condition.when(InstanceMethodReachabilityFacts.IS_PROVISIONALLY_INVOKED), ReachabilityFactsSetup::markEnclosingTypeAsProvisionallyInvoked);
        facts.registerInlineAction(Condition.when(InstanceMethodReachabilityFacts.IS_PROVISIONALLY_DISPATCH_INVOKED), ReachabilityFactsSetup::markEnclosingTypeAsProvisionallyDispatched);
        facts.registerInlineAction(Condition.whenAll(InstanceMethodReachabilityFacts.EXACT_RECEIVER_IS_ON_HEAP, InstanceMethodReachabilityFacts.IS_PROVISIONALLY_INVOKED), ReachabilityFactsSetup::markAsInvoked);
        facts.registerInlineAction(Condition.whenAll(InstanceMethodReachabilityFacts.DISPATCH_RECEIVER_IS_ON_HEAP, InstanceMethodReachabilityFacts.IS_PROVISIONALLY_DISPATCH_INVOKED), ReachabilityFactsSetup::markAsDispatchInvoked);
        facts.registerInlineAction(Condition.when(ObjectReachabilityFacts.IS_REACHABLE), ReachabilityFactsSetup::markObjectTypeDefAsOnHeap);
        facts.registerAction(Condition.when(ExecutableReachabilityFacts.IS_INVOKED), ReachabilityFactsSetup::markEnclosingAsInstantiatedIfCtor);
        // TODO: generate DISPATCH_RECEIVER_IS_ON_HEAP
        facts.registerAction(Condition.when(TypeReachabilityFacts.HAS_CLASS), (ltd, f) -> ReachabilityInfo.get(f.getCompilationContext()).getAnalysis().processReachableType(ltd, null));
    }

    private static void setupValidate(final Facts facts) {
        facts.registerInlineAction(Condition.when(ExecutableReachabilityFacts.IS_INVOKED), ReachabilityFactsSetup::validateWasInvoked);
    }

    // actions

    private static void validateWasInvoked(ExecutableElement me, Facts facts) {
        if (!facts.hadFact(me, ExecutableReachabilityFacts.IS_INVOKED)) {
            facts.getCompilationContext().error(me, "Element cannot become reachable after being unreachable in the previous phase");
        }
    }

    private static void markEachMethodAsInstantiated(LoadedTypeDefinition ltd, Facts facts) {
        ltd.forEachNonStaticMethod(facts, ReachabilityFactsSetup::markMethodWithOnHeapReceiver);
    }

    private static void markMethodWithOnHeapReceiver(Facts facts, InstanceMethodElement me) {
        facts.discover(me, InstanceMethodReachabilityFacts.EXACT_RECEIVER_IS_ON_HEAP);
    }

    private static void markEnclosingTypeAsProvisionallyInvoked(InstanceMethodElement me, Facts facts) {
        facts.discover(me.getEnclosingType().load(), TypeReachabilityFacts.ELEMENT_IS_PROVISIONALLY_INVOKED);
    }

    private static void markEnclosingTypeAsProvisionallyDispatched(InstanceMethodElement me, Facts facts) {
        facts.discover(me.getEnclosingType().load(), TypeReachabilityFacts.ELEMENT_IS_PROVISIONALLY_DISPATCH_INVOKED);
    }

    private static void markAsInvoked(InstanceMethodElement me, Facts facts) {
        facts.discover(me, ExecutableReachabilityFacts.IS_INVOKED);
    }

    private static void markAsDispatchInvoked(InstanceMethodElement me, Facts facts) {
        facts.discover(me, InstanceMethodReachabilityFacts.IS_DISPATCH_INVOKED);
    }

    private static void markEnclosingAsInstantiatedIfCtor(final ExecutableElement e, final Facts facts) {
        if (e instanceof ConstructorElement ce) {
            LoadedTypeDefinition type = ce.getEnclosingType().load();
            CompilationContext ctxt = type.getContext().getCompilationContext();
            Facts facts1 = Facts.get(ctxt);
            facts1.discover(type, TypeReachabilityFacts.IS_INSTANTIATED);
        }
    }

    private static void markObjectTypeDefAsOnHeap(VmObject obj, Facts facts) {
        facts.discover(obj.getVmClass().getTypeDefinition(), TypeReachabilityFacts.IS_ON_HEAP);
        // iterate fields of object to recursively mark them reachable
        PhysicalObjectType objectType = obj.getObjectType();
        LoadedTypeDefinition def = objectType.getDefinition().load();
        int fc = def.getFieldCount();
        for (int i = 0; i < fc; i++) {
            if (def.getField(i) instanceof InstanceFieldElement fe && fe.getType() instanceof ReferenceType) {
                VmObject nested = obj.getMemory().loadRef(fe.getOffset(), AccessModes.SinglePlain);
                if (nested != null) {
                    facts.discover(nested, ObjectReachabilityFacts.IS_REACHABLE);
                }
            }
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy