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

org.opalj.br.fpcf.analyses.VirtualCallAggregatingEscapeAnalysis.scala Maven / Gradle / Ivy

The newest version!
/* BSD 2-Clause License - see OPAL/LICENSE for details. */
package org.opalj
package br
package fpcf
package analyses

import org.opalj.fpcf.EOptionP
import org.opalj.fpcf.FinalP
import org.opalj.fpcf.InterimResult
import org.opalj.fpcf.InterimUBP
import org.opalj.fpcf.ProperPropertyComputationResult
import org.opalj.fpcf.PropertyBounds
import org.opalj.fpcf.PropertyStore
import org.opalj.fpcf.Result
import org.opalj.fpcf.SomeEOptionP
import org.opalj.fpcf.SomeEPS
import org.opalj.br.analyses.DeclaredMethodsKey
import org.opalj.br.analyses.ProjectInformationKeys
import org.opalj.br.analyses.SomeProject
import org.opalj.br.analyses.VirtualFormalParameter
import org.opalj.br.analyses.VirtualFormalParametersKey
import org.opalj.br.fpcf.properties.AtMost
import org.opalj.br.fpcf.properties.EscapeProperty
import org.opalj.br.fpcf.properties.GlobalEscape
import org.opalj.br.fpcf.properties.NoEscape
import org.opalj.br.fpcf.properties.VirtualMethodEscapeProperty

/**
 * Aggregates the escape information for virtual formal parameters.
 * That are all possible call targets that override the method attached to the virtual method.
 *
 * @see
 *      [[org.opalj.br.fpcf.properties.EscapeProperty]]
 *      [[org.opalj.br.analyses.VirtualFormalParameter]]
 *
 * @author Florian Kuebler
 */
class VirtualCallAggregatingEscapeAnalysis private[analyses] ( final val project: SomeProject) extends FPCFAnalysis {
    private[this] val formalParameters = project.get(VirtualFormalParametersKey)
    private[this] val declaredMethods = project.get(DeclaredMethodsKey)

    def determineEscape(fp: VirtualFormalParameter): ProperPropertyComputationResult = {
        val dm = fp.method
        assert(!dm.isInstanceOf[VirtualDeclaredMethod])

        if (dm.declaringClassType.isArrayType) {
            ??? //TODO handle case
        }

        // ANALYSIS STATE
        var escapeState: EscapeProperty = NoEscape
        var dependees: Set[SomeEOptionP] = Set.empty

        val cfo = project.classFile(dm.declaringClassType)
        val methods =
            if (cfo.isDefined && cfo.get.isInterfaceDeclaration)
                project.interfaceCall(
                    dm.declaringClassType,
                    dm.declaringClassType,
                    dm.name,
                    dm.descriptor
                )
            else project.virtualCall(
                dm.declaringClassType,
                dm.declaringClassType,
                dm.name,
                dm.descriptor
            )

        for (method <- methods) {
            val vfp = formalParameters(declaredMethods(method))(-1 - fp.origin)
            handleEscapeState(propertyStore(vfp, EscapeProperty.key))
        }

        def handleEscapeState(eOptionP: EOptionP[VirtualFormalParameter, EscapeProperty]): Unit =
            eOptionP match {
                case ep @ InterimUBP(p) =>
                    escapeState = escapeState meet p
                    dependees += ep
                case FinalP(p) => escapeState = escapeState meet p
                case epk       => dependees += epk
            }

        def returnResult: ProperPropertyComputationResult = {
            if (escapeState.isBottom || dependees.isEmpty)
                if (escapeState.isInstanceOf[AtMost])
                    //InterimResult(fp, GlobalEscape.asAggregatedProperty, escapeState.asAggregatedProperty, dependees, continuation)
                    Result(fp, escapeState.asAggregatedProperty)
                else
                    Result(fp, escapeState.asAggregatedProperty)
            else
                InterimResult(
                    fp, GlobalEscape.asAggregatedProperty, escapeState.asAggregatedProperty,
                    dependees, c
                )
        }

        def c(someEPS: SomeEPS): ProperPropertyComputationResult = {
            val other = someEPS.e

            assert(dependees.count(_.e eq other) <= 1)
            dependees = dependees filter { _.e ne other }
            handleEscapeState(someEPS.asInstanceOf[EOptionP[VirtualFormalParameter, EscapeProperty]])

            returnResult
        }

        returnResult
    }

}

sealed trait VirtualCallAggregatingEscapeAnalysisScheduler extends FPCFAnalysisScheduler {

    override def requiredProjectInformation: ProjectInformationKeys = Seq(
        VirtualFormalParametersKey,
        DeclaredMethodsKey
    )

    final override def uses: Set[PropertyBounds] = Set(PropertyBounds.lub(EscapeProperty))

    final def derivedProperty: PropertyBounds = PropertyBounds.lub(VirtualMethodEscapeProperty)

}

object EagerVirtualCallAggregatingEscapeAnalysis
    extends VirtualCallAggregatingEscapeAnalysisScheduler
    with BasicFPCFEagerAnalysisScheduler {

    override def derivesEagerly: Set[PropertyBounds] = Set(derivedProperty)

    override def derivesCollaboratively: Set[PropertyBounds] = Set.empty

    override def start(p: SomeProject, ps: PropertyStore, unused: Null): FPCFAnalysis = {
        val analysis = new VirtualCallAggregatingEscapeAnalysis(p)
        val vfps = p.get(VirtualFormalParametersKey).virtualFormalParameters
        ps.scheduleEagerComputationsForEntities(vfps)(analysis.determineEscape)
        analysis
    }
}

object LazyVirtualCallAggregatingEscapeAnalysis
    extends VirtualCallAggregatingEscapeAnalysisScheduler
    with BasicFPCFLazyAnalysisScheduler {

    override def derivesLazily: Some[PropertyBounds] = Some(derivedProperty)

    override def register(p: SomeProject, ps: PropertyStore, unused: Null): FPCFAnalysis = {
        val analysis = new VirtualCallAggregatingEscapeAnalysis(p)
        ps.registerLazyPropertyComputation(VirtualMethodEscapeProperty.key, analysis.determineEscape)
        analysis
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy