
org.opalj.br.fpcf.properties.AllocationFreeness.scala Maven / Gradle / Ivy
The newest version!
/* BSD 2-Clause License - see OPAL/LICENSE for details. */
package org.opalj
package br
package fpcf
package properties
import scala.annotation.switch
import org.opalj.fpcf.Entity
import org.opalj.fpcf.FallbackReason
import org.opalj.fpcf.OrderedProperty
import org.opalj.fpcf.PropertyKey
import org.opalj.fpcf.PropertyMetaInformation
import org.opalj.fpcf.PropertyStore
import org.opalj.br.instructions.ALOAD_0
import org.opalj.br.instructions.ANEWARRAY
import org.opalj.br.instructions.ASTORE_0
import org.opalj.br.instructions.GETFIELD
import org.opalj.br.instructions.INVOKEDYNAMIC
import org.opalj.br.instructions.INVOKEINTERFACE
import org.opalj.br.instructions.INVOKESPECIAL
import org.opalj.br.instructions.INVOKESTATIC
import org.opalj.br.instructions.INVOKEVIRTUAL
import org.opalj.br.instructions.MULTIANEWARRAY
import org.opalj.br.instructions.NEW
import org.opalj.br.instructions.NEWARRAY
import org.opalj.br.instructions.PUTFIELD
sealed trait AllocationFreenessPropertyMetaInformation extends PropertyMetaInformation {
final type Self = AllocationFreeness
}
/**
* Describes whether a [[org.opalj.br.DeclaredMethod]] or its (transitive) callees may allocate any
* objects/arrays.
*
* @author Dominik Helm
*/
sealed abstract class AllocationFreeness
extends OrderedProperty
with IndividualProperty[AllocationFreeness, VirtualMethodAllocationFreeness]
with AllocationFreenessPropertyMetaInformation {
/**
* The globally unique key of the [[AllocationFreeness]] property.
*/
final def key: PropertyKey[AllocationFreeness] = AllocationFreeness.key
final val aggregatedProperty = new VirtualMethodAllocationFreeness(this)
}
object AllocationFreeness extends AllocationFreenessPropertyMetaInformation {
/**
* The key associated with every allocation freeness property. The name is "AllocationFreeness";
* the fallback is "MethodWithAllocations".
*/
final val key = PropertyKey.create[DeclaredMethod, AllocationFreeness](
"AllocationFreeness",
(_: PropertyStore, _: FallbackReason, dm: DeclaredMethod) => {
if (dm.hasSingleDefinedMethod && dm.definedMethod.body.isDefined) {
val method = dm.definedMethod
val body = method.body.get
val instructions = body.instructions
val maxPC = instructions.length
var overwritesSelf = false
var mayOverwriteSelf = true
var hasAllocation = false
var currentPC = 0
while (currentPC < maxPC && !hasAllocation) {
val instruction = instructions(currentPC)
(instruction.opcode: @switch) match {
case NEW.opcode | NEWARRAY.opcode |
ANEWARRAY.opcode | MULTIANEWARRAY.opcode =>
hasAllocation = true
case INVOKESTATIC.opcode | INVOKESPECIAL.opcode | INVOKEVIRTUAL.opcode |
INVOKEINTERFACE.opcode | INVOKEDYNAMIC.opcode =>
hasAllocation = true
case ASTORE_0.opcode if !method.isStatic =>
if (mayOverwriteSelf) overwritesSelf = true
else hasAllocation = true
case PUTFIELD.opcode | GETFIELD.opcode => // may allocate NPE on non-receiver
if (method.isStatic || overwritesSelf)
hasAllocation = true
else if (instructions(body.pcOfPreviousInstruction(currentPC)).opcode !=
ALOAD_0.opcode)
hasAllocation = true
else
mayOverwriteSelf = false
case _ => hasAllocation = instruction.jvmExceptions.nonEmpty
}
currentPC = body.pcOfNextInstruction(currentPC)
}
if (hasAllocation) MethodWithAllocations else AllocationFreeMethod
} else MethodWithAllocations
}
)
}
/**
* The method does not allocate new objects/arrays and neither does any of its (transitive) callees.
*/
case object AllocationFreeMethod extends AllocationFreeness {
override def checkIsEqualOrBetterThan(e: Entity, other: AllocationFreeness): Unit = {}
override def meet(other: AllocationFreeness): AllocationFreeness = other
}
/**
* The method or any of its (transitive) callees may allocate new objects/arrays.
*/
case object MethodWithAllocations extends AllocationFreeness {
override def checkIsEqualOrBetterThan(e: Entity, other: AllocationFreeness): Unit = {
if (other ne MethodWithAllocations)
throw new IllegalArgumentException(s"$e: impossible refinement: $other => $this")
}
override def meet(other: AllocationFreeness): AllocationFreeness = this
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy