
org.opalj.br.fpcf.properties.FieldLocality.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 org.opalj.fpcf.FallbackReason
import org.opalj.fpcf.Property
import org.opalj.fpcf.PropertyKey
import org.opalj.fpcf.PropertyMetaInformation
import org.opalj.fpcf.PropertyStore
sealed trait FieldLocalityMetaInformation extends PropertyMetaInformation {
final type Self = FieldLocality
}
/**
* Describe the lifetime of the values stored in an instance field.
*
* [[LocalField]]s have a lifetime that is not longer than that of the field's owning instance.
* [[ExtensibleLocalField]]s provide the same guarantee only if the (dynamic) type of the owning
* instance is known not to extend `java.lang.Cloneable`.
* The lifetime of a value in a [[LocalFieldWithGetter]] can only be extended by it being returned
* by a method. I.e. if the caller of such method knows that it's receiver is fresh, the field's
* value may also be treated as fresh.
* [[ExtensibleLocalFieldWithGetter]] is used if both restrictions apply: The type type of the
* owning instance may not be cloneable and the value's lifetime could be extended by being
* returned by a method.
*/
sealed abstract class FieldLocality extends Property with FieldLocalityMetaInformation {
final def key: PropertyKey[FieldLocality] = FieldLocality.key
def meet(other: FieldLocality): FieldLocality
}
object FieldLocality extends FieldLocalityMetaInformation {
final lazy val key: PropertyKey[FieldLocality] = PropertyKey.create(
"FieldLocality",
(_: PropertyStore, _: FallbackReason, f: Field) => {
if (f.fieldType.isBaseType) LocalField else NoLocalField
}
)
}
/**
* A field that is always written with a fresh, non-escaping value. Values read from the field never
* escape. Therefore, the lifetime of such values is restricted by the lifetime of the field's
* owning instance.
*/
case object LocalField extends FieldLocality {
override def meet(other: FieldLocality): FieldLocality = other
}
/**
* The field is a [[LocalField]] only if the owning instance's (dynamic) type does not implement
* `java.lang.Cloneable`. Otherwise, the field's value may escape through a shallow copy created
* through `java.lang.Object.clone`.
*/
case object ExtensibleLocalField extends FieldLocality {
override def meet(other: FieldLocality): FieldLocality = other match {
case LocalField => this
case LocalFieldWithGetter => ExtensibleLocalFieldWithGetter
case _ => other
}
}
/**
* The field is a [[LocalField]] except that value's read from it may escape by being returned by
* a method of the owning instance. Clients can treat the value as fresh if the method's receiver is
* fresh.
*/
case object LocalFieldWithGetter extends FieldLocality {
override def meet(other: FieldLocality): FieldLocality = other match {
case LocalField => this
case ExtensibleLocalField => ExtensibleLocalFieldWithGetter
case _ => other
}
}
/**
* The field is a [[LocalField]] except that value's read from it may escape by being returned by
* a method of the owning instance. Also, the owning instance's (dynamic) type may not
* implement `java.lang.Cloneable` or the field may escape through a shallow copy. Clients can
* treat the field's value as fresh if the method's receiver is fresh and not cloneable.
*/
case object ExtensibleLocalFieldWithGetter extends FieldLocality {
override def meet(other: FieldLocality): FieldLocality = other match {
case NoLocalField => other
case _ => this
}
}
/**
* The field is not local, i.e. it may be written with non-fresh values or the fields's value may
* escape other than by being returned by a method of the owning instance.
*/
case object NoLocalField extends FieldLocality {
override def meet(other: FieldLocality): FieldLocality = this
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy