/* BSD 2-Clause License - see OPAL/LICENSE for details. */ package org.opalj package br package fpcf package properties import org.opalj.fpcf.Property import org.opalj.fpcf.PropertyKey import org.opalj.fpcf.PropertyMetaInformation sealed trait MethodComplexityPropertyMetaInformation extends PropertyMetaInformation { final type Self = MethodComplexity } /** * An upper bound for the maximum number of instructions that need to be evaluated * when the method is executed/interpreted. * Using this property enables other analyses to make a decision whether to "inline" method calls * or not. * For example, to improve the precision of an analysis it may be very useful to inline short * methods. Given the following code: * {{{ * def abs(i : Int) : Int = { * if(i == Int.MinValue) Int.MaxValue // COND + RETURN * else if(i < 0) -i // COND + RETURN * else i // RETURN * } // COMPLEXITY (BASED ON SOURCE CODE): 5 * * def ratio(i : Int, j : Int) : Int = { * abs(i) / abs(j) // HERE, when we do not inline abs calls, we have no idea about the final * // result; when we inline the abs calls, we can compute that the returned * // value will be positive or that the method throws a * // `DivisionByZeroException`. * } * }}} * * In general, the control flow graph is analyzed to compute an upper bound for the number * of evaluated instructions; as far as (easily) possible, loops are conceptually unrolled. If * the uppper bound could not be determined, the method is rated as being maximally complex. * * The complexity of called methods is generally not taken into account. However, invoke * instructions generally have a higher complexity than all other instructions to account for the * fact that method calls are more expensive than all other types of instructions. * * If an upper bound of a method's complexity cannot be estimated, the method will have * `Int.MaxValue` complexity. * * @param value The estimated complexity of a specific method ([0...`Int.MaxMavlue`]) * * @author Michael Eichberg */ case class MethodComplexity( value: Int ) extends Property with MethodComplexityPropertyMetaInformation { assert(value >= 0) final def key = MethodComplexity.key } object MethodComplexity extends MethodComplexityPropertyMetaInformation { final val TooComplex = MethodComplexity(Int.MaxValue) final val key = PropertyKey.create[Method, MethodComplexity]("MethodComplexity", TooComplex) }