
org.opalj.br.instructions.LDC2_W.scala Maven / Gradle / Ivy
The newest version!
/* BSD 2-Clause License - see OPAL/LICENSE for details. */
package org.opalj
package br
package instructions
import org.opalj.bytecode.BytecodeProcessingFailedException
/**
* Push long or double from runtime constant pool.
*
* @author Michael Eichberg
* @author Dominik Helm
*/
sealed abstract class LDC2_W[@specialized(Long, Double) T <: Any]
extends LoadConstantInstruction[T]
with InstructionMetaInformation {
final def opcode: Opcode = LDC2_W.opcode
final def mnemonic: String = "ldc2_w"
final def length: Int = 3
}
final case class LoadLong(value: Long) extends LDC2_W[Long] {
final def computationalType = ComputationalTypeLong
final def isIsomorphic(thisPC: PC, otherPC: PC)(implicit code: Code): Boolean = {
val other = code.instructions(otherPC)
(this eq other) || (
LDC2_W.opcode == other.opcode && other.isInstanceOf[LoadLong] &&
this.value == other.asInstanceOf[LoadLong].value
)
}
}
final case class LoadDouble(value: Double) extends LDC2_W[Double] {
final def computationalType = ComputationalTypeDouble
final def isIsomorphic(thisPC: PC, otherPC: PC)(implicit code: Code): Boolean = {
val other = code.instructions(otherPC)
this.similar(other)
}
override def similar(other: Instruction): Boolean = {
(this eq other) || (
LDC2_W.opcode == other.opcode && other.isInstanceOf[LoadDouble] && {
val otherLoadDouble = other.asInstanceOf[LoadDouble]
(this.value.isNaN && otherLoadDouble.value.isNaN) ||
(this.value == otherLoadDouble.value)
}
)
}
override def equals(other: Any): Boolean = {
other match {
case LoadDouble(thatValue) =>
thatValue == this.value || (thatValue.isNaN && this.value.isNaN)
case _ => false
}
}
// HashCode of "value.NaN" is stable and 0
}
/**
* @note To match [[LoadDynamic]], [[LoadDynamic_W]] and [[LoadDynamic2_W]] instructions you can use
* [[LDCDynamic]].
*/
final case class LoadDynamic2_W(
bootstrapMethod: BootstrapMethod,
name: String,
descriptor: FieldType
) extends LDC2_W[Nothing] {
def value: Nothing = throw new UnsupportedOperationException("dynamic constant unknown")
def computationalType: ComputationalType = descriptor.computationalType
final def isIsomorphic(thisPC: PC, otherPC: PC)(implicit code: Code): Boolean = {
val other = code.instructions(otherPC)
(this eq other) || this == other
}
}
case object INCOMPLETE_LDC2_W extends LDC2_W[Any] {
private def error: Nothing = {
val message = "this ldc2_w is incomplete"
throw BytecodeProcessingFailedException(message)
}
final def computationalType = error
final def value: Any = error
final def isIsomorphic(thisPC: PC, otherPC: PC)(implicit code: Code): Boolean = error
}
/**
* Defines factory and extractor methods for LDC2_W instructions.
*
* @author Michael Eichberg
*/
object LDC2_W {
final val opcode = 20
def apply(constantValue: ConstantValue[_]): LDC2_W[_] = {
constantValue.value match {
case v: Long => LoadLong(v)
case d: Double => LoadDouble(d)
case _ =>
throw BytecodeProcessingFailedException(
"unsupported LDC2_W constant value: "+constantValue
)
}
}
def unapply[T](ldc: LDC2_W[T]): Option[T] = Some(ldc.value)
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy