
org.opalj.br.fpcf.analyses.L0CompileTimeConstancyAnalysis.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.Entity
import org.opalj.fpcf.EOptionP
import org.opalj.fpcf.FinalP
import org.opalj.fpcf.InterimResult
import org.opalj.fpcf.ProperPropertyComputationResult
import org.opalj.fpcf.Property
import org.opalj.fpcf.PropertyBounds
import org.opalj.fpcf.PropertyStore
import org.opalj.fpcf.Result
import org.opalj.fpcf.SomeEPS
import org.opalj.fpcf.SomeInterimEP
import org.opalj.br.analyses.ProjectInformationKeys
import org.opalj.br.analyses.SomeProject
import org.opalj.br.fpcf.properties.CompileTimeConstancy
import org.opalj.br.fpcf.properties.CompileTimeConstantField
import org.opalj.br.fpcf.properties.CompileTimeVaryingField
import org.opalj.br.fpcf.properties.immutability.EffectivelyNonAssignable
import org.opalj.br.fpcf.properties.immutability.FieldAssignability
import org.opalj.br.fpcf.properties.immutability.LazilyInitialized
import org.opalj.br.fpcf.properties.immutability.NonAssignable
import org.opalj.br.fpcf.properties.immutability.UnsafelyLazilyInitialized
import org.opalj.fpcf.LBP
import org.opalj.fpcf.UBP
/**
* A simple analysis that identifies constant (effectively) final static fields that are
* deterministically initialized to the same value on every program execution.
* This analysis just examines the ConstantValue attribute of the field.
*
* @author Dominik Helm
*/
class L0CompileTimeConstancyAnalysis private[analyses] ( final val project: SomeProject)
extends FPCFAnalysis {
/**
* Determines the compile-time constancy of the field.
*
* This function encapsulates the continuation.
*/
def determineConstancy(field: Field): ProperPropertyComputationResult = {
if (!field.isStatic || field.constantFieldValue.isEmpty)
return Result(field, CompileTimeVaryingField);
if (field.isFinal)
return Result(field, CompileTimeConstantField);
var dependee: EOptionP[Entity, Property] = {
propertyStore(field, FieldAssignability.key) match {
case LBP(NonAssignable | EffectivelyNonAssignable) => return Result(field, CompileTimeConstantField);
case UBP(UnsafelyLazilyInitialized | LazilyInitialized) => return Result(field, CompileTimeVaryingField);
case ep => ep
}
}
// This function updates the compile-time constancy of the field when the field's
// mutability is updated
def c(eps: SomeEPS): ProperPropertyComputationResult = {
(eps: @unchecked) match {
case _: SomeInterimEP =>
dependee = eps
InterimResult(
field,
CompileTimeVaryingField,
CompileTimeConstantField,
Set(dependee),
c
)
case FinalP(NonAssignable) => Result(field, CompileTimeConstantField);
case FinalP(EffectivelyNonAssignable |
UnsafelyLazilyInitialized |
LazilyInitialized) => Result(field, CompileTimeVaryingField);
}
}
InterimResult(field, CompileTimeVaryingField, CompileTimeConstantField, Set(dependee), c)
}
/** Called when the analysis is scheduled lazily. */
def doDetermineConstancy(e: Entity): ProperPropertyComputationResult = {
e match {
case f: Field => determineConstancy(f)
case _ =>
throw new UnknownError("compile-time constancy is only defined for fields")
}
}
}
trait L0CompileTimeConstancyAnalysisScheduler extends FPCFAnalysisScheduler {
override def requiredProjectInformation: ProjectInformationKeys = Seq.empty
final override def uses: Set[PropertyBounds] = PropertyBounds.lubs(FieldAssignability)
final def derivedProperty: PropertyBounds = PropertyBounds.lub(CompileTimeConstancy)
}
object EagerL0CompileTimeConstancyAnalysis
extends L0CompileTimeConstancyAnalysisScheduler
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 L0CompileTimeConstancyAnalysis(p)
ps.scheduleEagerComputationsForEntities(p.allFields)(analysis.determineConstancy)
analysis
}
}
object LazyL0CompileTimeConstancyAnalysis
extends L0CompileTimeConstancyAnalysisScheduler
with BasicFPCFLazyAnalysisScheduler {
override def derivesLazily: Some[PropertyBounds] = Some(derivedProperty)
override def register(p: SomeProject, ps: PropertyStore, unused: Null): FPCFAnalysis = {
val analysis = new L0CompileTimeConstancyAnalysis(p)
ps.registerLazyPropertyComputation(CompileTimeConstancy.key, analysis.doDetermineConstancy)
analysis
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy