All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opalj.br.instructions.InvocationInstruction.scala Maven / Gradle / Ivy

The newest version!
/* BSD 2-Clause License - see OPAL/LICENSE for details. */
package org.opalj
package br
package instructions

/**
 * An instruction that "invokes" something. This can, e.g., be the invocation of a method
 * or – using [[INCOMPLETE_INVOKEDYNAMIC]] – the read of a field value.
 *
 * @author Michael Eichberg
 */
abstract class InvocationInstruction
    extends Instruction
    with ConstantLengthInstruction
    with NoLabels {

    final override def asInvocationInstruction: this.type = this

    final override def isInvocationInstruction: Boolean = true

    final def mayThrowExceptions: Boolean = true

    /**
     * The simple name of the called method.
     *
     * @note    This information is – in case of [[INCOMPLETE_INVOKEDYNAMIC]] instructions
     *          – only available after loading the entire class file.
     */
    def name: String

    /**
     * The method descriptor of the called method.
     *
     * @note    This information is – in case of [[INCOMPLETE_INVOKEDYNAMIC]] instructions
     *          – only available after loading the entire class file.
     */
    def methodDescriptor: MethodDescriptor

    /**
     * Returns `true` if this method takes an implicit parameter "this".
     */
    def isInstanceMethod: Boolean

    final def numberOfPushedOperands(ctg: Int => ComputationalTypeCategory): Int = {
        if (methodDescriptor.returnType.isVoidType) 0 else 1
    }

    final def stackSlotsChange: Int = {
        val returnType = methodDescriptor.returnType
        (if (isInstanceMethod) -1 /* pop "receiver object */ else 0) -
            methodDescriptor.parameterTypes.foldLeft(0)(_ + _.computationalType.operandSize) +
            (if (returnType.isVoidType) 0 else returnType.computationalType.operandSize)
    }

    final def expressionResult: ExpressionResultLocation = {
        if (methodDescriptor.returnType.isVoidType) NoExpression else Stack
    }

    final def isIsomorphic(thisPC: PC, otherPC: PC)(implicit code: Code): Boolean = {
        this == code.instructions(otherPC)
    }

    final def readsLocal: Boolean = false

    final def indexOfReadLocal: Int = throw new UnsupportedOperationException()

    final def writesLocal: Boolean = false

    final def indexOfWrittenLocal: Int = throw new UnsupportedOperationException()

    /**
     * Given that we have – without any sophisticated analysis – no idea which
     * exceptions may be thrown by the called method, we make the safe assumption that
     * any handler is a potential successor!
     *
     * The result may contain duplicates iff multiple different exceptions are handled by
     * the same handler. E.g., as generated in case of "Java's multicatch instruction":
     * {{{
     * try {} catch(IOException | NullPointerException ex) {...}
     * }}}
     */
    final def nextInstructions(
        currentPC:             PC,
        regularSuccessorsOnly: Boolean
    )(
        implicit
        code:           Code,
        classHierarchy: ClassHierarchy = ClassHierarchy.PreInitializedClassHierarchy
    ): List[PC] = {
        if (regularSuccessorsOnly)
            List(indexOfNextInstruction(currentPC))
        else {
            val exceptionHandlerPCs = code.handlerInstructionsFor(currentPC)
            indexOfNextInstruction(currentPC) :: exceptionHandlerPCs
        }
    }

    final override def toString(currentPC: Int): String = toString()
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy