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

org.opalj.br.reader.BytecodeReaderAndBinding.scala Maven / Gradle / Ivy

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

import scala.annotation.switch

import org.opalj.control.fillArraySeq
import org.opalj.control.fillIntArray
import org.opalj.bytecode.BytecodeProcessingFailedException
import org.opalj.br.instructions._
import org.opalj.collection.immutable.IntIntPair

/**
 * Defines a method to parse an array of bytes (containing Java bytecode instructions) and
 * to return an array of [[org.opalj.br.instructions.Instruction]]'s.
 *
 * The target array has the same size as the source array to make sure that branch offsets
 * etc. point to the correct instruction.
 *
 * @author Michael Eichberg
 */
trait BytecodeReaderAndBinding extends InstructionsDeserializer {

    /**
     * Transforms an array of bytes into an array of [[org.opalj.br.instructions.Instruction]]s.
     */
    def Instructions(
        cp:                  Constant_Pool,
        ap_name_index:       Constant_Pool_Index,
        ap_descriptor_index: Constant_Pool_Index,
        source:              Array[Byte]
    ): Instructions = {
        import java.io.DataInputStream
        import java.io.ByteArrayInputStream

        val bas = new ByteArrayInputStream(source)
        val in = new DataInputStream(bas)
        val codeLength = source.length
        val instructions = new Array[Instruction](codeLength)

        var wide: Boolean = false

        def lvIndex(): Int = {
            if (wide) {
                wide = false
                in.readUnsignedShort
            } else {
                in.readUnsignedByte
            }
        }

        while (in.available > 0) {
            val index = codeLength - in.available

            instructions(index) = (in.readUnsignedByte: @switch) match {
                case 50  => AALOAD
                case 83  => AASTORE
                case 1   => ACONST_NULL
                case 25  => ALOAD(lvIndex())
                case 42  => ALOAD_0
                case 43  => ALOAD_1
                case 44  => ALOAD_2
                case 45  => ALOAD_3
                case 189 => ANEWARRAY(cp(in.readUnsignedShort).asConstantValue(cp).toReferenceType)
                case 176 => ARETURN
                case 190 => ARRAYLENGTH
                case 58  => ASTORE(lvIndex())
                case 75  => ASTORE_0
                case 76  => ASTORE_1
                case 77  => ASTORE_2
                case 78  => ASTORE_3
                case 191 => ATHROW
                case 51  => BALOAD
                case 84  => BASTORE
                case 16  => BIPUSH(in.readByte.toInt /* value */ )
                case 52  => CALOAD
                case 85  => CASTORE
                case 192 =>
                    val referenceType = cp(in.readUnsignedShort).asConstantValue(cp).toReferenceType
                    CHECKCAST(referenceType)
                case 144 => D2F
                case 142 => D2I
                case 143 => D2L
                case 99  => DADD
                case 49  => DALOAD
                case 82  => DASTORE
                case 152 => DCMPG
                case 151 => DCMPL
                case 14  => DCONST_0
                case 15  => DCONST_1
                case 111 => DDIV
                case 24  => DLOAD(lvIndex())
                case 38  => DLOAD_0
                case 39  => DLOAD_1
                case 40  => DLOAD_2
                case 41  => DLOAD_3
                case 107 => DMUL
                case 119 => DNEG
                case 115 => DREM
                case 175 => DRETURN
                case 57  => DSTORE(lvIndex())
                case 71  => DSTORE_0
                case 72  => DSTORE_1
                case 73  => DSTORE_2
                case 74  => DSTORE_3
                case 103 => DSUB
                case 89  => DUP
                case 90  => DUP_X1
                case 91  => DUP_X2
                case 92  => DUP2
                case 93  => DUP2_X1
                case 94  => DUP2_X2
                case 141 => F2D
                case 139 => F2I
                case 140 => F2L
                case 98  => FADD
                case 48  => FALOAD
                case 81  => FASTORE
                case 150 => FCMPG
                case 149 => FCMPL
                case 11  => FCONST_0
                case 12  => FCONST_1
                case 13  => FCONST_2
                case 110 => FDIV
                case 23  => FLOAD(lvIndex())
                case 34  => FLOAD_0
                case 35  => FLOAD_1
                case 36  => FLOAD_2
                case 37  => FLOAD_3
                case 106 => FMUL
                case 118 => FNEG
                case 114 => FREM
                case 174 => FRETURN
                case 56  => FSTORE(lvIndex())
                case 67  => FSTORE_0
                case 68  => FSTORE_1
                case 69  => FSTORE_2
                case 70  => FSTORE_3
                case 102 => FSUB
                case 180 =>
                    val (declaringClass, name, fieldType): (ObjectType, String, FieldType) =
                        cp(in.readUnsignedShort).asFieldref(cp)
                    GETFIELD(declaringClass, name, fieldType)
                case 178 =>
                    val (declaringClass, name, fieldType): (ObjectType, String, FieldType) =
                        cp(in.readUnsignedShort).asFieldref(cp)
                    GETSTATIC(declaringClass, name, fieldType)
                case 167 => GOTO(in.readShort.toInt /* branchoffset */ )
                case 200 => GOTO_W(in.readInt /* branchoffset */ )
                case 145 => I2B
                case 146 => I2C
                case 135 => I2D
                case 134 => I2F
                case 133 => I2L
                case 147 => I2S
                case 96  => IADD
                case 46  => IALOAD
                case 126 => IAND
                case 79  => IASTORE
                case 2   => ICONST_M1
                case 3   => ICONST_0
                case 4   => ICONST_1
                case 5   => ICONST_2
                case 6   => ICONST_3
                case 7   => ICONST_4
                case 8   => ICONST_5
                case 108 => IDIV
                case 165 => IF_ACMPEQ(in.readShort.toInt)
                case 166 => IF_ACMPNE(in.readShort.toInt)
                case 159 => IF_ICMPEQ(in.readShort.toInt)
                case 160 => IF_ICMPNE(in.readShort.toInt)
                case 161 => IF_ICMPLT(in.readShort.toInt)
                case 162 => IF_ICMPGE(in.readShort.toInt)
                case 163 => IF_ICMPGT(in.readShort.toInt)
                case 164 => IF_ICMPLE(in.readShort.toInt)
                case 153 => IFEQ(in.readShort.toInt)
                case 154 => IFNE(in.readShort.toInt)
                case 155 => IFLT(in.readShort.toInt)
                case 156 => IFGE(in.readShort.toInt)
                case 157 => IFGT(in.readShort.toInt)
                case 158 => IFLE(in.readShort.toInt)
                case 199 => IFNONNULL(in.readShort.toInt)
                case 198 => IFNULL(in.readShort.toInt)
                case 132 =>
                    if (wide) {
                        wide = false
                        val lvIndex = in.readUnsignedShort
                        val constValue = in.readShort.toInt
                        IINC(lvIndex, constValue)
                    } else {
                        val lvIndex = in.readUnsignedByte
                        val constValue = in.readByte.toInt
                        IINC(lvIndex, constValue)
                    }
                case 21  => ILOAD(lvIndex())
                case 26  => ILOAD_0
                case 27  => ILOAD_1
                case 28  => ILOAD_2
                case 29  => ILOAD_3
                case 104 => IMUL
                case 116 => INEG
                case 193 => INSTANCEOF(cp(in.readUnsignedShort).asConstantValue(cp).toReferenceType)
                case 186 =>
                    // The invokeDynamicInfo constant pool entry cannot yet be resolved;
                    // we first need to load the BootstrapMethodTable attribute.
                    val invokeDynamicInfo = cp(in.readUnsignedShort).asInvokeDynamic
                    in.readByte // ignored; fixed value
                    in.readByte // ignored; fixed value
                    registerDeferredAction(cp) { classFile =>
                        deferredInvokedynamicResolution(
                            classFile,
                            cp,
                            ap_name_index,
                            ap_descriptor_index,
                            invokeDynamicInfo,
                            instructions,
                            index /* <=> pc */
                        )
                    }
                    INCOMPLETE_INVOKEDYNAMIC
                case 185 =>
                    val methodRef = cp(in.readUnsignedShort).asMethodref(cp)
                    val (declaringClass, _, name, methodDescriptor) = methodRef
                    in.readByte // ignored; fixed value
                    in.readByte // ignored; fixed value
                    INVOKEINTERFACE(declaringClass.asObjectType, name, methodDescriptor)
                case 183 =>
                    val methodRef = cp(in.readUnsignedShort).asMethodref(cp)
                    val (declaringClass, isInterface, name, methodDescriptor) = methodRef
                    INVOKESPECIAL(declaringClass.asObjectType, isInterface, name, methodDescriptor)
                case 184 =>
                    val methodRef = cp(in.readUnsignedShort).asMethodref(cp)
                    val (declaringClass, isInterface, name, methodDescriptor) = methodRef
                    INVOKESTATIC(declaringClass.asObjectType, isInterface, name, methodDescriptor)
                case 182 =>
                    val methodRef = cp(in.readUnsignedShort).asMethodref(cp)
                    val (declaringClass, _, name, methodDescriptor) = methodRef
                    INVOKEVIRTUAL(declaringClass, name, methodDescriptor)
                case 128 => IOR
                case 112 => IREM
                case 172 => IRETURN
                case 120 => ISHL
                case 122 => ISHR
                case 54  => ISTORE(lvIndex())
                case 59  => ISTORE_0
                case 60  => ISTORE_1
                case 61  => ISTORE_2
                case 62  => ISTORE_3
                case 100 => ISUB
                case 124 => IUSHR
                case 130 => IXOR
                case 168 => JSR(in.readShort.toInt)
                case 201 => JSR_W(in.readInt)
                case 138 => L2D
                case 137 => L2F
                case 136 => L2I
                case 97  => LADD
                case 47  => LALOAD
                case 127 => LAND
                case 80  => LASTORE
                case 148 => LCMP
                case 9   => LCONST_0
                case 10  => LCONST_1
                case 18 =>
                    val constant = cp(in.readUnsignedByte())
                    if (constant.isDynamic) {
                        registerDeferredAction(cp) { classFile =>
                            deferredDynamicConstantResolution(
                                classFile,
                                cp,
                                ap_name_index,
                                ap_descriptor_index,
                                constant.asDynamic,
                                instructions,
                                index /* <=> pc */
                            )
                        }
                        INCOMPLETE_LDC
                    } else {
                        LDC(constant.asConstantValue(cp))
                    }
                case 19 =>
                    val constant = cp(in.readUnsignedShort())
                    if (constant.isDynamic) {
                        registerDeferredAction(cp) { classFile =>
                            deferredDynamicConstantResolution(
                                classFile,
                                cp,
                                ap_name_index,
                                ap_descriptor_index,
                                constant.asDynamic,
                                instructions,
                                index /* <=> pc */
                            )
                        }
                        INCOMPLETE_LDC_W
                    } else {
                        LDC_W(constant.asConstantValue(cp))
                    }
                case 20 =>
                    val constant = cp(in.readUnsignedShort())
                    if (constant.isDynamic) {
                        registerDeferredAction(cp) { classFile =>
                            deferredDynamicConstantResolution(
                                classFile,
                                cp,
                                ap_name_index,
                                ap_descriptor_index,
                                constant.asDynamic,
                                instructions,
                                index /* <=> pc */
                            )
                        }
                        INCOMPLETE_LDC2_W
                    } else {
                        LDC2_W(constant.asConstantValue(cp))
                    }
                case 109 => LDIV
                case 22  => LLOAD(lvIndex())
                case 30  => LLOAD_0
                case 31  => LLOAD_1
                case 32  => LLOAD_2
                case 33  => LLOAD_3
                case 105 => LMUL
                case 117 => LNEG
                case 171 =>
                    in.skip((3 - (index % 4)).toLong) // skip padding bytes
                    val defaultOffset = in.readInt
                    val npairsCount = in.readInt
                    val npairs = fillArraySeq(npairsCount) { IntIntPair(in.readInt, in.readInt) }
                    LOOKUPSWITCH(defaultOffset, npairs)
                case 129 => LOR
                case 113 => LREM
                case 173 => LRETURN
                case 121 => LSHL
                case 123 => LSHR
                case 55  => LSTORE(lvIndex())
                case 63  => LSTORE_0
                case 64  => LSTORE_1
                case 65  => LSTORE_2
                case 66  => LSTORE_3
                case 101 => LSUB
                case 125 => LUSHR
                case 131 => LXOR
                case 194 => MONITORENTER
                case 195 => MONITOREXIT
                case 197 =>
                    MULTIANEWARRAY(
                        // componentType
                        cp(in.readUnsignedShort).asConstantValue(cp).toReferenceType.asArrayType,
                        //  dimensions
                        in.readUnsignedByte
                    )
                case 187 => NEW(cp(in.readUnsignedShort).asObjectType(cp))
                case 188 => NEWARRAY(in.readByte.toInt)
                case 0   => NOP
                case 87  => POP
                case 88  => POP2
                case 181 =>
                    val (declaringClass, name, fieldType): (ObjectType, String, FieldType) =
                        cp(in.readUnsignedShort).asFieldref(cp)
                    PUTFIELD(declaringClass, name, fieldType)
                case 179 =>
                    val (declaringClass, name, fieldType): (ObjectType, String, FieldType) =
                        cp(in.readUnsignedShort).asFieldref(cp)
                    PUTSTATIC(declaringClass, name, fieldType)
                case 169 =>
                    RET(
                        if (wide) {
                            wide = false
                            in.readUnsignedShort
                        } else {
                            in.readUnsignedByte
                        }
                    )
                case 177 => RETURN
                case 53  => SALOAD
                case 86  => SASTORE
                case 17  => SIPUSH(in.readShort.toInt /* value */ )
                case 95  => SWAP
                case 170 =>
                    in.skip((3 - (index % 4)).toLong) // skip padding bytes
                    val defaultOffset = in.readInt
                    val low = in.readInt
                    val high = in.readInt
                    val jumpOffsets = fillIntArray(high - low + 1) { in.readInt }
                    TABLESWITCH(defaultOffset, low, high, jumpOffsets)
                case 196 =>
                    wide = true
                    WIDE

                case opcode =>
                    throw BytecodeProcessingFailedException(s"unsupported opcode: $opcode")
            }

        }
        instructions
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy