sealed abstract class Purity extends IndividualProperty[Purity, VirtualMethodPurity] with PurityPropertyMetaInformation
Describes the level of the purity of a org.opalj.br.DeclaredMethod.
In general, a method is pure if its result only depends on its inputs and/or immutable global state and the execution of the method does not have any side effects; an instance method's inputs include the current object that is the receiver of the call.
The description of the purity levels is inspired by the definition found on wikipedia:
[...] a function may be considered a pure function if both of the following statements about the function hold:
- The function always evaluates to the same result value given the same argument value(s). The function result value cannot depend on any hidden information or state that may change while program execution proceeds or between different executions of the program, nor can it depend on any external input from I/O devices.
Hence, using true constants (e.g., Math.e) is not a problem as well as creating intermediate (mutable) data structures. More precisely, methods are pure if the values they refer to always (even across program runs) have an identical shape and the precise location in the heap is not relevant (e.g., java.lang.Object.hashCode() and ...toString() are not pure).
- Evaluation of the result does not cause any semantically observable side effect or output, such as mutation of mutable objects or output to I/O devices. The result value need not depend on all (or any) of the argument values. However, it must depend on nothing other than the argument values. The function may return multiple result values and these conditions must apply to all returned values for the function to be considered pure. If an argument is "call-by-reference", any parameter mutation will alter the value of the argument outside the function, which will render the function impure.
Given the preceding specification, the purity of a method is described by the subclasses of this property. In the following, the prefix of the names of the purity levels are used to identify the certainty of the computation of the purity; the letters have the following meaning:
- LB = Lower Bound; the method is at least <PURITY_LEVEL>, but can still be even more pure.
- C = Conditional; i.e., the current purity level depends on the purity level of other entities (These states are primarily used by the analysis to record the analysis progress.)
- D = The method is <PURITY_LEVEL> if certain Domain-specific (non-pure) operations are ignored.
ImpureByLackOfInformation methods have no constraints on their behavior. They may have side effect and
depend on all accessible (global) state. Analyses can always return (LB)Impure
as a safe
default value - even if they are not able to prove that a method is indeed impure; however,
in the latter case using ImpureByAnalysis is recommended as this enables subsequent analyses
to refine the property. There are several implementations of ImpureByAnalysis which give additional
reasoning why the analysis classified a method as impure.
SideEffectFree methods may depend on all accessible (and mutable) state, but may not have any side effects. In single-threaded execution, this means that the object graph of the program may not have changed between invocation of the method and its return, except for potentially additional objects allocated by the method. For multi-threaded execution, the object graph may not change due to the invocation of the method, again except allocation of new objects. Note that the object graph may change during execution of the method due to other methods executing on concurrent threads. The method must not have any effects (besides consumption of resources like memory and processor time) on methods executing concurrently, in particular it may not acquire any locks on objects that concurrent methods could also try to acquire.
Analyses may return SideEffectFree as a safe default value if they are unable to guarantee
that a method is Pure, even if it is. However, to return SideEffectFree
the analysis has
to guarantee that the method does not have any side effects.
Pure methods must be side effect free as described above and their result may only depend on their parameters (including the receiver object) and global constants. In particular, the result of a pure method must be structurally identical each time the method is invoked with structurally identical parameters. I.e., pure methods may depend on the aliasing relation between their parameters or between their parameters and global constants. E.g., the following method is pure:
def cmp(s: String) : Boolean = { // Reference(!) comparison of s with the interned string "Demo": s eq "Demo"; }
In multi-threaded execution, pure methods can not depend on any mutable state of their parameters if that state might be mutated by concurrently executing methods.
Analyses may return Pure only if they are able to guarantee that a method fulfills these requirements.
CompileTimePure methods additionally may only use global state that is compile-time constant (i.e., deterministically initialized to the same value on every execution of the program). If their return value is of a reference type, they must return the same reference each time they are invoked with identical parameters.
ExternallySideEffectFree
and ExternallyPure
methods are also similar to
SideEffectFree and Pure methods, respectively, but may modify their receiver object.
These properties may be used to detect changes that are confined because the receiver object is
under the control of the caller.
ContextuallySideEffectFree and ContextuallyPure methods may modifiy not only their receiver object but all of their parameters. Therefore, these properties can be used to detect confined changes because all parameters are under the control of the caller.
DSideEffectFree and DPure methods may perform actions that are
generally considered impure (or non-deterministic in the case of DPure
), but that
some clients may want to treat as pure. Such actions include, e.g. logging. A Rater
is used to
identify such actions and the properties contain a set of reasons assigned by the Rater.
DExternallySideEffectFree
and DExternallyPure
methods are similar, but may again
modify their receiver, while DContextuallySideEffectFree and DContextuallyPure
methods may modify their parameters.
ImpureByLackOfInformation is (also) used as the fallback value if no purity information could be computed for a method (no analysis is scheduled). Conceptually, clients must treat this in the same way as ImpureByAnalysis except that a future refinement may be possible in case of ImpureByAnalysis.
- Source
- Purity.scala
- Alphabetic
- By Inheritance
- Purity
- PurityPropertyMetaInformation
- IndividualProperty
- AggregatableValueProperty
- Property
- PropertyMetaInformation
- PropertyKind
- AnyRef
- Any
- Hide All
- Show All
- Public
- Protected
Type Members
- final type Self = Purity
- Definition Classes
- PurityPropertyMetaInformation → PropertyMetaInformation
- type self = Purity
- Definition Classes
- IndividualProperty → AggregatableValueProperty
Abstract Value Members
- abstract val flags: Int
Concrete Value Members
- final def !=(arg0: Any): Boolean
- Definition Classes
- AnyRef → Any
- final def ##: Int
- Definition Classes
- AnyRef → Any
- final def ==(arg0: Any): Boolean
- Definition Classes
- AnyRef → Any
- final def aggregatedProperty: VirtualMethodPurity
- Definition Classes
- Purity → IndividualProperty
- final def asInstanceOf[T0]: T0
- Definition Classes
- Any
- final def asOrderedProperty: OrderedProperty
Returns
this
if this property inherits from OrderedProperty.Returns
this
if this property inherits from OrderedProperty.Used, e.g., by the framework to support debugging analyses.
- Definition Classes
- Property
- def clone(): AnyRef
- Attributes
- protected[lang]
- Definition Classes
- AnyRef
- Annotations
- @throws(classOf[java.lang.CloneNotSupportedException]) @native() @IntrinsicCandidate()
- final def eq(arg0: AnyRef): Boolean
- Definition Classes
- AnyRef
- def equals(arg0: AnyRef): Boolean
- Definition Classes
- AnyRef → Any
- final def getClass(): Class[_ <: AnyRef]
- Definition Classes
- AnyRef → Any
- Annotations
- @native() @IntrinsicCandidate()
- def hashCode(): Int
- Definition Classes
- AnyRef → Any
- Annotations
- @native() @IntrinsicCandidate()
- final def id: Int
The id uniquely identifies this property's category.
The id uniquely identifies this property's category. All property objects of the same kind have to use the same id which is guaranteed since they share the same
PropertyKey
- Definition Classes
- PropertyMetaInformation → PropertyKind
- def isCompileTimePure: Boolean
- def isDeterministic: Boolean
- final def isInstanceOf[T0]: Boolean
- Definition Classes
- Any
- final def isOrderedProperty: Boolean
Returns
true
if this property inherits from OrderedProperty.Returns
true
if this property inherits from OrderedProperty.- Definition Classes
- Property
- final def key: PropertyKey[Purity]
The globally unique key of the Purity property.
The globally unique key of the Purity property.
- Definition Classes
- Purity → PropertyMetaInformation
- def meet(other: Purity): Purity
Combines this purity value with another one to represent the progress by a purity analysis in one phase.
Combines this purity value with another one to represent the progress by a purity analysis in one phase. Conditional as well as unconditional values are combined to the purity level that expresses a weaker purity, thereby incorporating the effect of counter-examples to a stronger purity. Thus, the result of this operation is used to represent a (potentially conditional) upper bound on the possible final result of the purity analysis that performs this operation. If one of the combined purity values is conditional and the other is not, the result will be the same as if the conditional purity value was combined with the conditional value that corresponds to the unconditional value.
- Definition Classes
- Purity → AggregatableValueProperty
- val modifiedParams: IntTrieSet
- def modifiesParameters: Boolean
- final def ne(arg0: AnyRef): Boolean
- Definition Classes
- AnyRef
- final def notify(): Unit
- Definition Classes
- AnyRef
- Annotations
- @native() @IntrinsicCandidate()
- final def notifyAll(): Unit
- Definition Classes
- AnyRef
- Annotations
- @native() @IntrinsicCandidate()
- final def synchronized[T0](arg0: => T0): T0
- Definition Classes
- AnyRef
- def toString(): String
- Definition Classes
- AnyRef → Any
- def usesDomainSpecificActions: Boolean
- final def wait(arg0: Long, arg1: Int): Unit
- Definition Classes
- AnyRef
- Annotations
- @throws(classOf[java.lang.InterruptedException])
- final def wait(arg0: Long): Unit
- Definition Classes
- AnyRef
- Annotations
- @throws(classOf[java.lang.InterruptedException])
- final def wait(): Unit
- Definition Classes
- AnyRef
- Annotations
- @throws(classOf[java.lang.InterruptedException])
- def withoutContextual: Purity
Deprecated Value Members
- def finalize(): Unit
- Attributes
- protected[lang]
- Definition Classes
- AnyRef
- Annotations
- @throws(classOf[java.lang.Throwable]) @Deprecated
- Deprecated