alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Scala example source code file (JCode.java)

This example Scala source code file (JCode.java) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - Scala tags/keywords

exceptionhandler, io, ioexception, jmethod, jmethodtype, jtype, label, label, offsettoobigexception, offsettoobigexception, string, string, stringbuffer, unknown_stack_size, unknown_stack_size, util

The Scala JCode.java source code

/* FJBG -- Fast Java Bytecode Generator
 * Copyright 2002-2011 LAMP/EPFL
 * @author  Michel Schinz
 */

package ch.epfl.lamp.fjbg;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.*;

import ch.epfl.lamp.util.ByteArray;

/**
 * List of instructions, to which Java byte-code instructions can be added.
 *
 * @author Michel Schinz, Thomas Friedli
 * @version 1.0
 */

public class JCode {
    protected boolean frozen = false;

    protected final FJBGContext context;
    protected final JMethod owner;

    protected final ByteArray codeArray;

    protected final LinkedList/*<ExceptionHandler>*/ exceptionHandlers =
        new LinkedList();

    protected final JConstantPool pool;

    protected final ArrayList/*<OffsetToPatch>*/ offsetToPatch =
        new ArrayList();

    protected static int UNKNOWN_STACK_SIZE = Integer.MIN_VALUE;
    protected int maxStackSize = UNKNOWN_STACK_SIZE;
    protected int[] stackProduction = null;
    protected int[] stackSizes;

    protected JCode(FJBGContext context, JClass clazz, JMethod owner) {
        this.context = context;
        this.pool = clazz.getConstantPool();
        this.owner = owner;
        this.codeArray = new ByteArray();
    }

    protected JCode(FJBGContext context,
                    JClass clazz,
                    JMethod owner,
                    DataInputStream stream)
        throws IOException {
        this.context = context;
        this.pool = clazz.getConstantPool();
        this.owner = owner;
        owner.setCode(this);
        int size = stream.readInt();
        if (size >= 65536) // section 4.10
            throw new Error("code size must be less than 65536: " + size);
        this.codeArray = new ByteArray(stream, size);
    }

    /**
     * Gets the program counter, which is defined as the address of the
     * next instruction.
     * @return The int representing the value of the program counter
     */
    public int getPC() {
        return codeArray.getSize();
    }

    /**
     * Gets the size of the code
     * @return The number of bytes of the code
     */
    public int getSize() {
        return codeArray.getSize();
    }

    /**
     * Gets the method to which the code belongs
     * @return The method to which the code belongs
     */
    public JMethod getOwner() {
        return owner;
    }

    // Stack size
    public int getMaxStackSize() {
        if (maxStackSize == UNKNOWN_STACK_SIZE)
            maxStackSize = computeMaxStackSize();
        return maxStackSize;
    }

    // Freezing
    //////////////////////////////////////////////////////////////////////

    public void freeze() throws OffsetTooBigException {
        assert !frozen;
        patchAllOffset();
        codeArray.freeze();
        frozen = true;
    }

    // Attributes
    //////////////////////////////////////////////////////////////////////

    protected final LinkedList/*<JAttribute>*/ attributes = new LinkedList();

    public void addAttribute(JAttribute attr) {
        attributes.add(attr);
    }

    public List/*<JAttribute>*/ getAttributes() {
        return attributes;
    }

    // Emitting code
    //////////////////////////////////////////////////////////////////////

    public void emit(JOpcode opcode) {
        setStackProduction(getPC(), opcode);
        codeArray.addU1(opcode.code);
    }

    public void emitNOP() { emit(JOpcode.NOP); }

    // Constant loading.
    public void emitACONST_NULL() { emit(JOpcode.ACONST_NULL); }
    public void emitICONST_M1() { emit(JOpcode.ICONST_M1); }
    public void emitICONST_0() { emit(JOpcode.ICONST_0); }
    public void emitICONST_1() { emit(JOpcode.ICONST_1); }
    public void emitICONST_2() { emit(JOpcode.ICONST_2); }
    public void emitICONST_3() { emit(JOpcode.ICONST_3); }
    public void emitICONST_4() { emit(JOpcode.ICONST_4); }
    public void emitICONST_5() { emit(JOpcode.ICONST_5); }
    public void emitLCONST_0() { emit(JOpcode.LCONST_0); }
    public void emitLCONST_1() { emit(JOpcode.LCONST_1); }
    public void emitFCONST_0() { emit(JOpcode.FCONST_0); }
    public void emitFCONST_1() { emit(JOpcode.FCONST_1); }
    public void emitFCONST_2() { emit(JOpcode.FCONST_2); }
    public void emitDCONST_0() { emit(JOpcode.DCONST_0); }
    public void emitDCONST_1() { emit(JOpcode.DCONST_1); }

    public void emitBIPUSH(int b) { emitU1(JOpcode.BIPUSH, b); }
    public void emitSIPUSH(int s) { emitU2(JOpcode.SIPUSH, s); }
    public void emitLDC(int value) {
        emitU1(JOpcode.LDC, pool.addInteger(value));
    }
    public void emitLDC(float value) {
        emitU1(JOpcode.LDC, pool.addFloat(value));
    }
    public void emitLDC(String value) {
        emitU1(JOpcode.LDC, pool.addString(value));
    }
    public void emitLDC_W(int value) {
        emitU1(JOpcode.LDC_W, pool.addInteger(value));
    }
    public void emitLDC_W(float value) {
        emitU1(JOpcode.LDC_W, pool.addFloat(value));
    }
    public void emitLDC_W(String value) {
        emitU1(JOpcode.LDC_W, pool.addString(value));
    }
    public void emitLDC2_W(long value) {
        emitU2(JOpcode.LDC2_W, pool.addLong(value));
    }
    public void emitLDC2_W(double value) {
        emitU2(JOpcode.LDC2_W, pool.addDouble(value));
    }

    // Loading variables.
    public void emitILOAD(int index) { emitU1(JOpcode.ILOAD, index); }
    public void emitLLOAD(int index) { emitU1(JOpcode.LLOAD, index); }
    public void emitFLOAD(int index) { emitU1(JOpcode.FLOAD, index); }
    public void emitDLOAD(int index) { emitU1(JOpcode.DLOAD, index); }
    public void emitALOAD(int index) { emitU1(JOpcode.ALOAD, index); }

    public void emitILOAD_0() { emit(JOpcode.ILOAD_0); }
    public void emitILOAD_1() { emit(JOpcode.ILOAD_1); }
    public void emitILOAD_2() { emit(JOpcode.ILOAD_2); }
    public void emitILOAD_3() { emit(JOpcode.ILOAD_3); }
    public void emitLLOAD_0() { emit(JOpcode.LLOAD_0); }
    public void emitLLOAD_1() { emit(JOpcode.LLOAD_1); }
    public void emitLLOAD_2() { emit(JOpcode.LLOAD_2); }
    public void emitLLOAD_3() { emit(JOpcode.LLOAD_3); }
    public void emitFLOAD_0() { emit(JOpcode.FLOAD_0); }
    public void emitFLOAD_1() { emit(JOpcode.FLOAD_1); }
    public void emitFLOAD_2() { emit(JOpcode.FLOAD_2); }
    public void emitFLOAD_3() { emit(JOpcode.FLOAD_3); }
    public void emitDLOAD_0() { emit(JOpcode.DLOAD_0); }
    public void emitDLOAD_1() { emit(JOpcode.DLOAD_1); }
    public void emitDLOAD_2() { emit(JOpcode.DLOAD_2); }
    public void emitDLOAD_3() { emit(JOpcode.DLOAD_3); }
    public void emitALOAD_0() { emit(JOpcode.ALOAD_0); }
    public void emitALOAD_1() { emit(JOpcode.ALOAD_1); }
    public void emitALOAD_2() { emit(JOpcode.ALOAD_2); }
    public void emitALOAD_3() { emit(JOpcode.ALOAD_3); }

    public void emitIALOAD() { emit(JOpcode.IALOAD); }
    public void emitLALOAD() { emit(JOpcode.LALOAD); }
    public void emitFALOAD() { emit(JOpcode.FALOAD); }
    public void emitDALOAD() { emit(JOpcode.DALOAD); }
    public void emitAALOAD() { emit(JOpcode.AALOAD); }
    public void emitBALOAD() { emit(JOpcode.BALOAD); }
    public void emitCALOAD() { emit(JOpcode.CALOAD); }
    public void emitSALOAD() { emit(JOpcode.SALOAD); }

    // Storing variables.
    public void emitISTORE(int index) { emitU1(JOpcode.ISTORE, index); }
    public void emitLSTORE(int index) { emitU1(JOpcode.LSTORE, index); }
    public void emitFSTORE(int index) { emitU1(JOpcode.FSTORE, index); }
    public void emitDSTORE(int index) { emitU1(JOpcode.DSTORE, index); }
    public void emitASTORE(int index) { emitU1(JOpcode.ASTORE, index); }

    public void emitISTORE_0() { emit(JOpcode.ISTORE_0); }
    public void emitISTORE_1() { emit(JOpcode.ISTORE_1); }
    public void emitISTORE_2() { emit(JOpcode.ISTORE_2); }
    public void emitISTORE_3() { emit(JOpcode.ISTORE_3); }
    public void emitLSTORE_0() { emit(JOpcode.LSTORE_0); }
    public void emitLSTORE_1() { emit(JOpcode.LSTORE_1); }
    public void emitLSTORE_2() { emit(JOpcode.LSTORE_2); }
    public void emitLSTORE_3() { emit(JOpcode.LSTORE_3); }
    public void emitFSTORE_0() { emit(JOpcode.FSTORE_0); }
    public void emitFSTORE_1() { emit(JOpcode.FSTORE_1); }
    public void emitFSTORE_2() { emit(JOpcode.FSTORE_2); }
    public void emitFSTORE_3() { emit(JOpcode.FSTORE_3); }
    public void emitDSTORE_0() { emit(JOpcode.DSTORE_0); }
    public void emitDSTORE_1() { emit(JOpcode.DSTORE_1); }
    public void emitDSTORE_2() { emit(JOpcode.DSTORE_2); }
    public void emitDSTORE_3() { emit(JOpcode.DSTORE_3); }
    public void emitASTORE_0() { emit(JOpcode.ASTORE_0); }
    public void emitASTORE_1() { emit(JOpcode.ASTORE_1); }
    public void emitASTORE_2() { emit(JOpcode.ASTORE_2); }
    public void emitASTORE_3() { emit(JOpcode.ASTORE_3); }

    public void emitIASTORE() { emit(JOpcode.IASTORE); }
    public void emitLASTORE() { emit(JOpcode.LASTORE); }
    public void emitFASTORE() { emit(JOpcode.FASTORE); }
    public void emitDASTORE() { emit(JOpcode.DASTORE); }
    public void emitAASTORE() { emit(JOpcode.AASTORE); }
    public void emitBASTORE() { emit(JOpcode.BASTORE); }
    public void emitCASTORE() { emit(JOpcode.CASTORE); }
    public void emitSASTORE() { emit(JOpcode.SASTORE); }

    // Stack manipulation.
    public void emitPOP() { emit(JOpcode.POP); }
    public void emitPOP2() { emit(JOpcode.POP2); }
    public void emitDUP() { emit(JOpcode.DUP); }
    public void emitDUP_X1() { emit(JOpcode.DUP_X1); }
    public void emitDUP_X2() { emit(JOpcode.DUP_X2); }
    public void emitDUP2() { emit(JOpcode.DUP2); }
    public void emitDUP2_X1() { emit(JOpcode.DUP2_X1); }
    public void emitDUP2_X2() { emit(JOpcode.DUP2_X2); }
    public void emitSWAP() { emit(JOpcode.SWAP); }

    // Artithmetic and logic operations.
    public void emitIADD() { emit(JOpcode.IADD); }
    public void emitLADD() { emit(JOpcode.LADD); }
    public void emitFADD() { emit(JOpcode.FADD); }
    public void emitDADD() { emit(JOpcode.DADD); }

    public void emitISUB() { emit(JOpcode.ISUB); }
    public void emitLSUB() { emit(JOpcode.LSUB); }
    public void emitFSUB() { emit(JOpcode.FSUB); }
    public void emitDSUB() { emit(JOpcode.DSUB); }

    public void emitIMUL() { emit(JOpcode.IMUL); }
    public void emitLMUL() { emit(JOpcode.LMUL); }
    public void emitFMUL() { emit(JOpcode.FMUL); }
    public void emitDMUL() { emit(JOpcode.DMUL); }

    public void emitIDIV() { emit(JOpcode.IDIV); }
    public void emitLDIV() { emit(JOpcode.LDIV); }
    public void emitFDIV() { emit(JOpcode.FDIV); }
    public void emitDDIV() { emit(JOpcode.DDIV); }

    public void emitIREM() { emit(JOpcode.IREM); }
    public void emitLREM() { emit(JOpcode.LREM); }
    public void emitFREM() { emit(JOpcode.FREM); }
    public void emitDREM() { emit(JOpcode.DREM); }

    public void emitINEG() { emit(JOpcode.INEG); }
    public void emitLNEG() { emit(JOpcode.LNEG); }
    public void emitFNEG() { emit(JOpcode.FNEG); }
    public void emitDNEG() { emit(JOpcode.DNEG); }

    public void emitISHL() { emit(JOpcode.ISHL); }
    public void emitLSHL() { emit(JOpcode.LSHL); }

    public void emitISHR() { emit(JOpcode.ISHR); }
    public void emitLSHR() { emit(JOpcode.LSHR); }

    public void emitIUSHR() { emit(JOpcode.IUSHR); }
    public void emitLUSHR() { emit(JOpcode.LUSHR); }

    public void emitIAND() { emit(JOpcode.IAND); }
    public void emitLAND() { emit(JOpcode.LAND); }

    public void emitIOR() { emit(JOpcode.IOR); }
    public void emitLOR() { emit(JOpcode.LOR); }

    public void emitIXOR() { emit(JOpcode.IXOR); }
    public void emitLXOR() { emit(JOpcode.LXOR); }

    public void emitIINC(int index, int increment) {
        emitU1U1(JOpcode.IINC, index, increment);
    }

    // (Numeric) type conversions.
    public void emitI2L() { emit(JOpcode.I2L); }
    public void emitI2F() { emit(JOpcode.I2F); }
    public void emitI2D() { emit(JOpcode.I2D); }
    public void emitL2I() { emit(JOpcode.L2I); }
    public void emitL2F() { emit(JOpcode.L2F); }
    public void emitL2D() { emit(JOpcode.L2D); }
    public void emitF2I() { emit(JOpcode.F2I); }
    public void emitF2L() { emit(JOpcode.F2L); }
    public void emitF2D() { emit(JOpcode.F2D); }
    public void emitD2I() { emit(JOpcode.D2I); }
    public void emitD2L() { emit(JOpcode.D2L); }
    public void emitD2F() { emit(JOpcode.D2F); }
    public void emitI2B() { emit(JOpcode.I2B); }
    public void emitI2C() { emit(JOpcode.I2C); }
    public void emitI2S() { emit(JOpcode.I2S); }

    // Comparisons and tests.
    public void emitLCMP() { emit(JOpcode.LCMP); }
    public void emitFCMPL() { emit(JOpcode.FCMPL); }
    public void emitFCMPG() { emit(JOpcode.FCMPG); }
    public void emitDCMPL() { emit(JOpcode.DCMPL); }
    public void emitDCMPG() { emit(JOpcode.DCMPG); }

    protected void emitGenericIF(JOpcode opcode, Label label)
        throws OffsetTooBigException {
        emitU2(opcode, label.getOffset16(getPC() + 1, getPC()));
    }

    public void emitIFEQ(Label label) throws OffsetTooBigException {
        emitGenericIF(JOpcode.IFEQ, label);
    }
    public void emitIFEQ(int targetPC) throws OffsetTooBigException {
        emitU2(JOpcode.IFEQ, targetPC - getPC());
    }
    public void emitIFEQ() {
        emitU2(JOpcode.IFEQ, 0);
    }

    public void emitIFNE(Label label) throws OffsetTooBigException {
        emitGenericIF(JOpcode.IFNE, label);
    }
    public void emitIFNE(int targetPC) throws OffsetTooBigException {
        emitU2(JOpcode.IFNE, targetPC - getPC());
    }
    public void emitIFNE() {
        emitU2(JOpcode.IFNE, 0);
    }

    public void emitIFLT(Label label) throws OffsetTooBigException {
        emitGenericIF(JOpcode.IFLT, label);
    }
    public void emitIFLT(int targetPC) throws OffsetTooBigException {
        emitU2(JOpcode.IFLT, targetPC - getPC());
    }
    public void emitIFLT() {
        emitU2(JOpcode.IFLT, 0);
    }

    public void emitIFGE(Label label) throws OffsetTooBigException {
        emitGenericIF(JOpcode.IFGE, label);
    }
    public void emitIFGE(int targetPC) throws OffsetTooBigException {
        emitU2(JOpcode.IFGE, targetPC - getPC());
    }
    public void emitIFGE() {
        emitU2(JOpcode.IFGE, 0);
    }

    public void emitIFGT(Label label) throws OffsetTooBigException {
        emitGenericIF(JOpcode.IFGT, label);
    }
    public void emitIFGT(int targetPC) throws OffsetTooBigException {
        emitU2(JOpcode.IFGT, targetPC - getPC());
    }
    public void emitIFGT() {
        emitU2(JOpcode.IFGT, 0);
    }

    public void emitIFLE(Label label) throws OffsetTooBigException {
        emitGenericIF(JOpcode.IFLE, label);
    }
    public void emitIFLE(int targetPC) throws OffsetTooBigException {
        emitU2(JOpcode.IFLE, targetPC - getPC());
    }
    public void emitIFLE() {
        emitU2(JOpcode.IFLE, 0);
    }

    public void emitIF_ICMPEQ(Label label) throws OffsetTooBigException {
        emitGenericIF(JOpcode.IF_ICMPEQ, label);
    }
    public void emitIF_ICMPEQ(int targetPC) throws OffsetTooBigException {
        emitU2(JOpcode.IF_ICMPEQ, targetPC - getPC());
    }
    public void emitIF_ICMPEQ() {
        emitU2(JOpcode.IF_ICMPEQ, 0);
    }

    public void emitIF_ICMPNE(Label label) throws OffsetTooBigException {
        emitGenericIF(JOpcode.IF_ICMPNE, label);
    }
    public void emitIF_ICMPNE(int targetPC) throws OffsetTooBigException {
        emitU2(JOpcode.IF_ICMPNE, targetPC - getPC());
    }
    public void emitIF_ICMPNE() {
        emitU2(JOpcode.IF_ICMPNE, 0);
    }

    public void emitIF_ICMPLT(Label label) throws OffsetTooBigException {
        emitGenericIF(JOpcode.IF_ICMPLT, label);
    }
    public void emitIF_ICMPLT(int targetPC) throws OffsetTooBigException {
        emitU2(JOpcode.IF_ICMPLT, targetPC - getPC());
    }
    public void emitIF_ICMPLT() {
        emitU2(JOpcode.IF_ICMPLT, 0);
    }

    public void emitIF_ICMPGE(Label label) throws OffsetTooBigException {
        emitGenericIF(JOpcode.IF_ICMPGE, label);
    }
    public void emitIF_ICMPGE(int targetPC) throws OffsetTooBigException {
        emitU2(JOpcode.IF_ICMPGE, targetPC - getPC());
    }
    public void emitIF_ICMPGE() {
        emitU2(JOpcode.IF_ICMPGE, 0);
    }

    public void emitIF_ICMPGT(Label label) throws OffsetTooBigException {
        emitGenericIF(JOpcode.IF_ICMPGT, label);
    }
    public void emitIF_ICMPGT(int targetPC) throws OffsetTooBigException {
        emitU2(JOpcode.IF_ICMPGT, targetPC - getPC());
    }
    public void emitIF_ICMPGT() {
        emitU2(JOpcode.IF_ICMPGT, 0);
    }

    public void emitIF_ICMPLE(Label label) throws OffsetTooBigException {
        emitGenericIF(JOpcode.IF_ICMPLE, label);
    }
    public void emitIF_ICMPLE(int targetPC) throws OffsetTooBigException {
        emitU2(JOpcode.IF_ICMPLE, targetPC - getPC());
    }
    public void emitIF_ICMPLE() {
        emitU2(JOpcode.IF_ICMPLE, 0);
    }

    public void emitIF_ACMPEQ(Label label) throws OffsetTooBigException {
        emitGenericIF(JOpcode.IF_ACMPEQ, label);
    }
    public void emitIF_ACMPEQ(int targetPC) throws OffsetTooBigException {
        emitU2(JOpcode.IF_ACMPEQ, targetPC - getPC());
    }
    public void emitIF_ACMPEQ() {
        emitU2(JOpcode.IF_ACMPEQ, 0);
    }

    public void emitIF_ACMPNE(Label label) throws OffsetTooBigException {
        emitGenericIF(JOpcode.IF_ACMPNE, label);
    }
    public void emitIF_ACMPNE(int targetPC) throws OffsetTooBigException {
        emitU2(JOpcode.IF_ACMPNE, targetPC - getPC());
    }
    public void emitIF_ACMPNE() {
        emitU2(JOpcode.IF_ACMPNE, 0);
    }

    public void emitIFNULL(Label label) throws OffsetTooBigException {
        emitGenericIF(JOpcode.IFNULL, label);
    }
    public void emitIFNULL(int targetPC) throws OffsetTooBigException {
        emitU2(JOpcode.IFNULL, targetPC - getPC());
    }
    public void emitIFNULL() {
        emitU2(JOpcode.IFNULL, 0);
    }

    public void emitIFNONNULL(Label label) throws OffsetTooBigException {
        emitGenericIF(JOpcode.IFNONNULL, label);
    }
    public void emitIFNONNULL(int targetPC) throws OffsetTooBigException {
        emitU2(JOpcode.IFNONNULL, targetPC - getPC());
    }
    public void emitIFNONNULL() {
        emitU2(JOpcode.IFNONNULL, 0);
    }

    public void emitGOTO(Label label) throws OffsetTooBigException {
        emitU2(JOpcode.GOTO, label.getOffset16(getPC() + 1, getPC()));
    }
    public void emitGOTO(int targetPC) throws OffsetTooBigException {
        int offset = targetPC - getPC();
        checkOffset16(offset);
        emitU2(JOpcode.GOTO, offset);
    }
    public void emitGOTO() {
        emitU2(JOpcode.GOTO, 0);
    }

    public void emitGOTO_W(Label label) {
        emitU4(JOpcode.GOTO_W, label.getOffset32(getPC() + 1, getPC()));
    }
    public void emitGOTO_W(int targetPC) {
        emitU4(JOpcode.GOTO_W, targetPC - getPC());
    }
    public void emitGOTO_W() {
        emitU4(JOpcode.GOTO_W, 0);
    }

    public void emitJSR(Label label) throws OffsetTooBigException {
        emitU2(JOpcode.JSR, label.getOffset16(getPC() + 1, getPC()));
    }
    public void emitJSR(int targetPC) {
        emitU2(JOpcode.JSR, targetPC - getPC());
    }
    public void emitJSR() {
        emitU2(JOpcode.JSR, 0);
    }

    public void emitJSR_W(Label label) {
        emitU4(JOpcode.JSR_W, label.getOffset32(getPC() + 1, getPC()));
    }
    public void emitJSR_W(int targetPC) {
        emitU4(JOpcode.JSR_W, targetPC - getPC());
    }
    public void emitJSR_W() {
        emitU4(JOpcode.JSR_W, 0);
    }

    /*
    public void emitRET(Label label) throws OffsetTooBigException {
        emitU2(JOpcode.RET, label.getOffset16(getPC() + 1, getPC()));
    }
    public void emitRET(int targetPC) {
        emitU1(JOpcode.RET, targetPC);
    }
    public void emitRET() {
        emitU1(JOpcode.RET, 0);
    }
    */

    public void emitRET(int index) {
        emitU1(JOpcode.RET, index);
    }

    public void emitRET(JLocalVariable var) {
        emitRET(var.getIndex());
    }

    public void emitTABLESWITCH(int[] keys,
                     Label[] branches,
                     Label defaultBranch) {
        assert keys.length == branches.length;

        int low = keys[0], high = keys[keys.length - 1];
        int instrPC = getPC();

        setStackProduction(instrPC, JOpcode.TABLESWITCH);
        codeArray.addU1(JOpcode.cTABLESWITCH);
        while (getPC() % 4 != 0) codeArray.addU1(0);

        codeArray.addU4(defaultBranch.getOffset32(getPC(), instrPC));
        codeArray.addU4(low);
        codeArray.addU4(high);
        for (int i = 0; i < branches.length; i++) {
            assert keys[i] == low + i;
            codeArray.addU4(branches[i].getOffset32(getPC(), instrPC));
        }
    }

    public void emitLOOKUPSWITCH(int[] keys,
                     Label[] branches,
                     Label defaultBranch) {
        assert keys.length == branches.length;

        int instrPC = getPC();
        setStackProduction(getPC(), JOpcode.LOOKUPSWITCH);
        codeArray.addU1(JOpcode.cLOOKUPSWITCH);
        while (getPC() % 4 != 0) codeArray.addU1(0);

        codeArray.addU4(defaultBranch.getOffset32(getPC(), instrPC));
        codeArray.addU4(branches.length);
        for (int i = 0; i < branches.length; i++) {
            codeArray.addU4(keys[i]);
            codeArray.addU4(branches[i].getOffset32(getPC(), instrPC));
        }
    }

    public void emitIRETURN() { emit(JOpcode.IRETURN); }
    public void emitLRETURN() { emit(JOpcode.LRETURN); }
    public void emitFRETURN() { emit(JOpcode.FRETURN); }
    public void emitDRETURN() { emit(JOpcode.DRETURN); }
    public void emitARETURN() { emit(JOpcode.ARETURN); }
    public void emitRETURN() { emit(JOpcode.RETURN); }

    // Field access
    public void emitGETSTATIC(String className, String name, JType type) {
        setStackProduction(getPC(), type.getSize());
        int index = pool.addFieldRef(className, name, type.getSignature());
        emitU2(JOpcode.GETSTATIC, index);
    }
    public void emitPUTSTATIC(String className, String name, JType type) {
        setStackProduction(getPC(), -type.getSize());
        int index = pool.addFieldRef(className, name, type.getSignature());
        emitU2(JOpcode.PUTSTATIC, index);
    }
    public void emitGETFIELD(String className, String name, JType type) {
        setStackProduction(getPC(), type.getSize() - 1);
        int index = pool.addFieldRef(className, name, type.getSignature());
        emitU2(JOpcode.GETFIELD, index);
    }
    public void emitPUTFIELD(String className, String name, JType type) {
        setStackProduction(getPC(), -(type.getSize() + 1));
        int index = pool.addFieldRef(className, name, type.getSignature());
        emitU2(JOpcode.PUTFIELD, index);
    }

    // Method invocation
    public void emitINVOKEVIRTUAL(String className,
                                  String name,
                                  JMethodType type) {
        setStackProduction(getPC(), type.getProducedStack() - 1);
        int index =
            pool.addClassMethodRef(className, name, type.getSignature());
        emitU2(JOpcode.INVOKEVIRTUAL, index);
    }
    public void emitINVOKESPECIAL(String className,
                                  String name,
                                  JMethodType type) {
        setStackProduction(getPC(), type.getProducedStack() - 1);
        int index =
            pool.addClassMethodRef(className, name, type.getSignature());
        emitU2(JOpcode.INVOKESPECIAL, index);
    }
    public void emitINVOKESTATIC(String className,
                                 String name,
                                 JMethodType type) {
        setStackProduction(getPC(), type.getProducedStack());
        int index =
            pool.addClassMethodRef(className, name, type.getSignature());
        emitU2(JOpcode.INVOKESTATIC, index);
    }
    public void emitINVOKEINTERFACE(String className,
                                    String name,
                                    JMethodType type) {
        setStackProduction(getPC(), type.getProducedStack() - 1);
        int index =
            pool.addInterfaceMethodRef(className, name, type.getSignature());
        emitU2U1U1(JOpcode.INVOKEINTERFACE, index, type.getArgsSize() + 1, 0);
    }

    // Object creation
    public void emitNEW(String className) {
        emitU2(JOpcode.NEW, pool.addClass(className));
    }
    public void emitNEWARRAY(JType elemType) {
        emitU1(JOpcode.NEWARRAY, elemType.getTag());
    }
    public void emitANEWARRAY(JReferenceType elemType) {
        emitU2(JOpcode.ANEWARRAY, pool.addDescriptor(elemType));
    }
    public void emitMULTIANEWARRAY(JReferenceType elemType, int dimensions) {
        setStackProduction(getPC(), -dimensions + 1);
        emitU2U1(JOpcode.MULTIANEWARRAY,
                 pool.addDescriptor(elemType),
                 dimensions);
    }
    public void emitARRAYLENGTH() { emit(JOpcode.ARRAYLENGTH); }

    // Exception throwing
    public void emitATHROW() { emit(JOpcode.ATHROW); }

    // Dynamic typing
    public void emitCHECKCAST(JReferenceType type) {
        emitU2(JOpcode.CHECKCAST, pool.addDescriptor(type));
    }
    public void emitINSTANCEOF(JReferenceType type) {
        emitU2(JOpcode.INSTANCEOF, pool.addDescriptor(type));
    }

    // Monitors
    public void emitMONITORENTER() { emit(JOpcode.MONITORENTER); }
    public void emitMONITOREXIT() { emit(JOpcode.MONITOREXIT); }

    // Wide variants
    // FIXME setStackProd. will here raise an exception
    public void emitWIDE(JOpcode opcode, int index) {
        assert (opcode.code == JOpcode.cILOAD)
            || (opcode.code == JOpcode.cLLOAD)
            || (opcode.code == JOpcode.cFLOAD)
            || (opcode.code == JOpcode.cDLOAD)
            || (opcode.code == JOpcode.cALOAD)
            || (opcode.code == JOpcode.cISTORE)
            || (opcode.code == JOpcode.cLSTORE)
            || (opcode.code == JOpcode.cFSTORE)
            || (opcode.code == JOpcode.cDSTORE)
            || (opcode.code == JOpcode.cASTORE)
            || (opcode.code == JOpcode.cRET)
            : "invalide opcode for WIDE: " + opcode;

        setStackProduction(getPC(), opcode);
        codeArray.addU1(JOpcode.WIDE.code);
        codeArray.addU1(opcode.code);
        codeArray.addU2(index);
    }
    public void emitWIDE(JOpcode opcode, int index, int constant) {
        assert opcode.code == JOpcode.cIINC
            : "invalid opcode for WIDE: " + opcode;

        setStackProduction(getPC(), opcode);
        codeArray.addU1(JOpcode.cWIDE);
        codeArray.addU1(opcode.code);
        codeArray.addU2(index);
        codeArray.addU2(constant);
    }

    protected void emitU1(JOpcode opcode, int i1) {
        setStackProduction(getPC(), opcode);
        codeArray.addU1(opcode.code);
        codeArray.addU1(i1);
    }

    protected void emitU1U1(JOpcode opcode, int i1, int i2) {
        setStackProduction(getPC(), opcode);
        codeArray.addU1(opcode.code);
        codeArray.addU1(i1);
        codeArray.addU1(i2);
    }

    protected void emitU2(JOpcode opcode, int i1) {
        setStackProduction(getPC(), opcode);
        codeArray.addU1(opcode.code);
        codeArray.addU2(i1);
    }

    protected void emitU2U1(JOpcode opcode, int i1, int i2) {
        setStackProduction(getPC(), opcode);
        codeArray.addU1(opcode.code);
        codeArray.addU2(i1);
        codeArray.addU1(i2);
    }

    protected void emitU2U1U1(JOpcode opcode, int i1, int i2, int i3) {
        setStackProduction(getPC(), opcode);
        codeArray.addU1(opcode.code);
        codeArray.addU2(i1);
        codeArray.addU1(i2);
        codeArray.addU1(i3);
    }

    protected void emitU4(JOpcode opcode, int i1) {
        setStackProduction(getPC(), opcode);
        codeArray.addU1(opcode.code);
        codeArray.addU4(i1);
    }

    protected int getU1(int sourcePos) {
        return codeArray.getU1(sourcePos);
    }

    protected int getU2(int sourcePos) {
        return codeArray.getU2(sourcePos);
    }

    protected int getU4(int sourcePos) {
        return codeArray.getU4(sourcePos);
    }

    protected int getS1(int sourcePos) {
        return codeArray.getS1(sourcePos);
    }

    protected int getS2(int sourcePos) {
        return codeArray.getS2(sourcePos);
    }

    protected int getS4(int sourcePos) {
        return codeArray.getS4(sourcePos);
    }

    // Stack size computation
    //////////////////////////////////////////////////////////////////////

    protected int getStackProduction(int pc) {
        if (stackProduction == null || pc >= stackProduction.length)
            return UNKNOWN_STACK_SIZE;
        else
            return stackProduction[pc];
    }

    protected void setStackProduction(int pc, int production) {
        if (stackProduction == null) {
            stackProduction = new int[256];
            Arrays.fill(stackProduction, UNKNOWN_STACK_SIZE);
        } else {
            while (pc >= stackProduction.length) {
                    int[] newStackProduction = new int[stackProduction.length * 2];
                    System.arraycopy(stackProduction, 0,
                                     newStackProduction, 0,
                                     stackProduction.length);
                    Arrays.fill(newStackProduction,
                                stackProduction.length,
                                newStackProduction.length,
                                UNKNOWN_STACK_SIZE);
                    stackProduction = newStackProduction;
                }
        }
        stackProduction[pc] = production;
    }

    protected void setStackProduction(int pc, JOpcode opcode) {
        // TODO we should instead check whether the opcode has known
        // stack consumption/production.
        if (getStackProduction(pc) == UNKNOWN_STACK_SIZE) 
//                && opcode.hasKnownProducedDataSize()
//                && opcode.hasKnownConsumedDataSize())
            setStackProduction(pc,
                               opcode.getProducedDataSize()
                               - opcode.getConsumedDataSize());
    }

    protected int computeMaxStackSize() {
        if (stackSizes == null) {
            stackSizes = new int[getSize()];
            Arrays.fill(stackSizes, UNKNOWN_STACK_SIZE);
            stackSizes[0] = 0;
        }
        int size = computeMaxStackSize(0, 0, 0);
        
        // compute stack sizes for exception handlers too
        ExceptionHandler exh = null;
        for (Iterator it = exceptionHandlers.iterator();
             it.hasNext();) {
            exh = (ExceptionHandler)it.next();
            int exhSize = computeMaxStackSize(exh.getHandlerPC(), 1, 1);
            if (size < exhSize)
                size = exhSize;
        }

        return size;
    }

    protected int computeMaxStackSize(int pc, int stackSize, int maxStackSize) {
        JCodeIterator iterator = new JCodeIterator(this, pc);
        for (;;) {
            int successors = iterator.getSuccessorCount();
            if (successors == 0)
                return maxStackSize;
            else {
                assert stackProduction[iterator.getPC()] != UNKNOWN_STACK_SIZE
                    : "unknown stack production, pc=" + iterator.getPC()
                    + " in method " + owner.getName();
                stackSize += stackProduction[iterator.getPC()];
                if (stackSize > maxStackSize)
                    maxStackSize = stackSize;
                int nextPC = -1;
                for (int i = 0; i < successors; ++i) {
                    int succPC = iterator.getSuccessorPC(i);
                    assert succPC >= 0 && succPC < stackSizes.length
                        : iterator.getPC() + ": invalid pc: " + succPC
                        + " op: " + iterator.getOpcode();
                    if (stackSizes[succPC] == UNKNOWN_STACK_SIZE) {
                        stackSizes[succPC] = stackSize;
                        if (nextPC == -1)
                            nextPC = succPC;
                        else
                            maxStackSize = computeMaxStackSize(succPC,
                                                               stackSize,
                                                               maxStackSize);
                    }
                }
                if (nextPC == -1)
                    return maxStackSize;
                else
                    iterator.moveTo(nextPC);
            }
        }
    }

    // Labels
    //////////////////////////////////////////////////////////////////////

    public static class OffsetTooBigException extends Exception {
        public OffsetTooBigException() { super(); }
        public OffsetTooBigException(String message) { super(message); }
    }

    protected void checkOffset16(int offset) throws OffsetTooBigException {
        if (offset < Short.MIN_VALUE || offset > Short.MAX_VALUE)
            throw new OffsetTooBigException("offset too big to fit"
                                            + " in 16 bits: " + offset);
    }

    public class Label {
        protected boolean anchored = false;
        protected int targetPC = 0;

        public void anchorToNext() {
            assert !anchored;
            this.targetPC = getPC();
            anchored = true;
        }

        public int getAnchor() {
            assert anchored;
            return targetPC;
        }

        protected int getOffset16(int pc, int instrPC)
            throws OffsetTooBigException {
            if (anchored) {
                int offset = targetPC - instrPC;
                checkOffset16(offset);
                return offset;
            } else {
                recordOffsetToPatch(pc, 16, instrPC, this);
                return 0;
            }
        }

        protected int getOffset32(int pc, int instrPC) {
            if (anchored)
                return targetPC - instrPC;
            else {
                recordOffsetToPatch(pc, 32, instrPC, this);
                return 0;
            }
        }
    }

    public Label newLabel() {
        return new Label();
    }

    public Label[] newLabels(int count) {
        Label[] labels = new Label[count];
        for (int i = 0; i < labels.length; ++i)
            labels[i] = newLabel();
        return labels;
    }

    protected static class OffsetToPatch {
        public final int pc;
        public final int size;
        public final int instrPC;
        public final Label label;

        public OffsetToPatch(int pc, int size, int instrPC, Label label) {
            this.pc = pc;
            this.size = size;
            this.instrPC = instrPC;
            this.label = label;
        }
    }

    protected void recordOffsetToPatch(int offsetPC,
                                       int size,
                                       int instrPC,
                                       Label label) {
        offsetToPatch.add(new OffsetToPatch(offsetPC, size, instrPC, label));
    }

    protected void patchAllOffset() throws OffsetTooBigException {
        Iterator offsetIt = offsetToPatch.iterator();
        while (offsetIt.hasNext()) {
            OffsetToPatch offset = (OffsetToPatch)offsetIt.next();
            int offsetValue = offset.label.getAnchor() - offset.instrPC;
            if (offset.size == 16) {
                checkOffset16(offsetValue);
                codeArray.putU2(offset.pc, offsetValue);
            } else
                codeArray.putU4(offset.pc, offsetValue);
        }
    }

    // Exception handling
    //////////////////////////////////////////////////////////////////////

    public class ExceptionHandler {
        protected int startPC, endPC, handlerPC;
        protected final String catchType;
        protected final int catchTypeIndex;

        public void setStartPC(int pc) {
            this.startPC = pc;
        }
        
        public int getStartPC() {
            return this.startPC;
        }

        public void setEndPC(int pc) {
            this.endPC = pc;
        }
        
        public int getEndPC() {
            return this.endPC;
        }

        public void setHandlerPC(int pc) {
            this.handlerPC = pc;
        }
        
        public int getHandlerPC() {
            return this.handlerPC;
        }

        public ExceptionHandler(String catchType) {
            this(0, 0, 0, catchType);
        }

        public ExceptionHandler(int startPC,
                                   int endPC,
                                   int handlerPC,
                                   String catchType) {
            this.startPC = startPC;
            this.endPC = endPC;
            this.handlerPC = handlerPC;
            this.catchType = catchType;
            this.catchTypeIndex = (catchType == null
                                   ? 0
                                   : pool.addClass(catchType));
        }

        public ExceptionHandler(DataInputStream stream) throws IOException {
            this.startPC = stream.readShort();
            this.endPC = stream.readShort();
            this.handlerPC = stream.readShort();
            this.catchTypeIndex = stream.readShort();
            this.catchType = (catchTypeIndex == 0
                              ? null
                              : pool.lookupClass(catchTypeIndex));
        }

        public void writeTo(DataOutputStream stream) throws IOException {
            stream.writeShort(startPC);
            stream.writeShort(endPC);
            stream.writeShort(handlerPC);
            stream.writeShort(catchTypeIndex);
        }

        // Follows javap output format for exception handlers.
        /*@Override*/public String toString() {
            StringBuffer buf = new StringBuffer("    ");
            if (startPC < 10) buf.append(" ");
            buf.append(startPC);
            buf.append("    ");
            if (endPC < 10) buf.append(" ");
            buf.append(endPC);
            buf.append("    ");
            buf.append(handlerPC);
            buf.append("   ");
            if (catchType != null) {
                buf.append("Class ");
                buf.append(catchType);
            }
            else
                buf.append("any");
            return buf.toString();
        }

    }

    public void addExceptionHandler(ExceptionHandler handler) {
        assert !frozen;
        exceptionHandlers.add(handler);
    }

    public void addExceptionHandler(int startPC,
                                    int endPC,
                                    int handlerPC,
                                    String catchType) {
        addExceptionHandler(new ExceptionHandler(startPC,
                                                 endPC,
                                                 handlerPC,
                                                 catchType));
    }

    public void addFinallyHandler(int startPC, int endPC, int handlerPC) {
        assert !frozen;
        addExceptionHandler(startPC, endPC, handlerPC, null);
    }

    public List/*<ExceptionHandler>*/ getExceptionHandlers() {
        return exceptionHandlers;
    }

    // Line numbers
    //////////////////////////////////////////////////////////////////////

    protected int[] lineNumbers = null;
    protected void ensureLineNumberCapacity(int endPC) {
        assert !frozen;
        if (lineNumbers == null) {
            lineNumbers = new int[endPC];
            addAttribute(context.JLineNumberTableAttribute(owner.getOwner(),
                                                           this));
        } else if (lineNumbers.length < endPC) {
            int[] newLN = new int[Math.max(endPC, lineNumbers.length * 2)];
            System.arraycopy(lineNumbers, 0, newLN, 0, lineNumbers.length);
            lineNumbers = newLN;
        }
    }

    /**
     * Set all line numbers in the interval [startPC, endPC) to
     * line, overwriting existing line numbers.
     */
    public void setLineNumber(int startPC, int endPC, int line) {
        ensureLineNumberCapacity(endPC);
        Arrays.fill(lineNumbers, startPC, endPC, line);
    }

    public void setLineNumber(int instrPC, int line) {
        setLineNumber(instrPC, instrPC + 1, line);
    }

    /** Sets all non-filled line numbers in the interval [startPC, endPC)
     *  to 'line'.
     */
    public void completeLineNumber(int startPC, int endPC, int line) {
        ensureLineNumberCapacity(endPC);
        for (int pc = startPC; pc < endPC; ++pc)
            if (lineNumbers[pc] == 0) lineNumbers[pc] = line;
    }

    public int[] getLineNumbers() {
        assert frozen;
        if (lineNumbers == null) return new int[0];
        else if (lineNumbers.length == getPC()) return lineNumbers;
        else {
            int[] trimmedLN = new int[getPC()];
            System.arraycopy(lineNumbers, 0,
                             trimmedLN, 0,
                             Math.min(lineNumbers.length, trimmedLN.length));
            return trimmedLN;
        }
    }

    // Output
    //////////////////////////////////////////////////////////////////////

    public void writeTo(DataOutputStream stream) throws IOException {
        assert frozen;
        stream.writeInt(getSize());
        codeArray.writeTo(stream);
    }

    // Follows javap output format for opcodes.
    /*@Override*/ public String toString() {
        StringBuffer buf = new StringBuffer();
        JOpcode opcode = null;
        int pc = 0, addr = 0;
        while (pc < codeArray.getSize()) {
            buf.append("\n   ");
            buf.append(pc);
            buf.append(":\t");
            opcode = JOpcode.OPCODES[codeArray.getU1(pc)];
            buf.append(decode(opcode, pc));
            if (opcode.code == JOpcode.cTABLESWITCH ||
                opcode.code == JOpcode.cLOOKUPSWITCH) {
                addr = ((pc / 4 + 1) + 1) * 4; // U4 aligned data
                int low = codeArray.getU4(addr);
                int high = codeArray.getU4(addr+4);
                pc = addr + (2/*low+high*/ + (high - low + 1)/*targets*/) * 4;
            } else
                pc += opcode.getSize();
        }
        if (exceptionHandlers.size() > 0) {
            buf.append("\n  Exception table:\n   from   to  target type\n");
            Iterator it = exceptionHandlers.iterator();
            while (it.hasNext()) {
                ExceptionHandler exh = (ExceptionHandler)it.next();
                buf.append(exh);
                buf.append("\n");
            }
        }
        return buf.toString();
    }

    private String decode(JOpcode opcode, int pc) {
        String ownerClassName = owner.getOwner().getName();
        int data, data2;
        StringBuilder buf = new StringBuilder();
        buf.append(opcode.name.toLowerCase());
        switch (opcode.code) {
        case JOpcode.cALOAD: case JOpcode.cASTORE: case JOpcode.cBIPUSH:
        case JOpcode.cDLOAD: case JOpcode.cDSTORE:
        case JOpcode.cFLOAD: case JOpcode.cFSTORE:
        case JOpcode.cILOAD: case JOpcode.cISTORE:
        case JOpcode.cLLOAD: case JOpcode.cLSTORE:
            data = codeArray.getU1(pc+1);
            buf.append("\t");
            buf.append(data);
            break;     
        case JOpcode.cLDC:
            data = codeArray.getU1(pc+1);
            buf.append("\t#");
            buf.append(data);
            buf.append("; ");
            buf.append(pool.lookupEntry(data).toComment(ownerClassName));
            break;
        case JOpcode.cNEWARRAY:
            data = codeArray.getU1(pc+1);
            buf.append(" ");
            buf.append(JType.tagToString(data));
            break;
        case JOpcode.cIINC:
            data = codeArray.getU1(pc+1);
            data2 = codeArray.getU1(pc+2);
            buf.append("\t");
            buf.append(data);
            buf.append(", ");
            buf.append(data2);
            break;
        case JOpcode.cSIPUSH:
            data = codeArray.getU2(pc+1);
            buf.append("\t");
            buf.append(data);
            break;
        case JOpcode.cANEWARRAY: case JOpcode.cCHECKCAST:
        case JOpcode.cGETFIELD: case JOpcode.cGETSTATIC:
        case JOpcode.cINSTANCEOF:
        case JOpcode.cINVOKESPECIAL: case JOpcode.cINVOKESTATIC:
        case JOpcode.cINVOKEVIRTUAL:
        case JOpcode.cLDC_W: case JOpcode.cLDC2_W: case JOpcode.cNEW:
        case JOpcode.cPUTFIELD: case JOpcode.cPUTSTATIC:
            data = codeArray.getU2(pc+1);
            buf.append("\t#");
            buf.append(data);
            buf.append("; ");
            buf.append(pool.lookupEntry(data).toComment(ownerClassName));
            break;
        case JOpcode.cIF_ACMPEQ: case JOpcode.cIF_ACMPNE:
        case JOpcode.cIFEQ: case JOpcode.cIFGE: case JOpcode.cIFGT:
        case JOpcode.cIFLE: case JOpcode.cIFLT: case JOpcode.cIFNE:
        case JOpcode.cIFNONNULL: case JOpcode.cIFNULL:
        case JOpcode.cIF_ICMPEQ: case JOpcode.cIF_ICMPGE:
        case JOpcode.cIF_ICMPGT: case JOpcode.cIF_ICMPLE:
        case JOpcode.cIF_ICMPLT: case JOpcode.cIF_ICMPNE:
            data = codeArray.getU2(pc+1); // maybe S2 offset
            buf.append("\t");
            buf.append(pc+data);
            break;
        case JOpcode.cGOTO:
            data = codeArray.getS2(pc+1); // always S2 offset
            buf.append("\t");
            buf.append(pc+data);
            break;
        case JOpcode.cINVOKEINTERFACE:
            data = codeArray.getU2(pc+1);
            data2 = codeArray.getU1(pc+3);
            buf.append("\t#");
            buf.append(data);
            buf.append(",  ");
            buf.append(data2);
            buf.append("; ");
            buf.append(pool.lookupEntry(data).toComment(ownerClassName));
            break;
        case JOpcode.cTABLESWITCH:
            buf.append("{ //");
            int addr = ((pc / 4 + 1) + 1) * 4; // U4 aligned data
            int low = codeArray.getU4(addr);
            int high = codeArray.getU4(addr+4);
            buf.append(low);
            buf.append(" to ");
            buf.append(high);
            for (int i = low; i <= high; ++i) {
                buf.append("\n\t\t");
                buf.append(i);
                buf.append(": ");
                buf.append(pc+codeArray.getU4(addr+(i-1)*4));
                buf.append(";");
            }
            buf.append("\n\t\tdefault: ");
            buf.append(pc+codeArray.getU4(addr-4));
            buf.append(" }");
        default:
        }
        return buf.toString();
    }
}

Other Scala examples (source code examples)

Here is a short list of links related to this Scala JCode.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.